1

我一直在尝试使用“pimpl”习语,但我就是无法编译该死的东西。

在带有 g++ v. 4.6.3 的 Linux Mint 上,我收到以下错误:

$ g++ main.cc 
/tmp/ccXQ9X9O.o: In function `main':
main.cc:(.text+0xd7): undefined reference to `Person::Person(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)'
collect2: ld returned 1 exit status

这是我的代码:

人.hh

#ifndef PERSON_HH
#define PERSON_HH

#include <tr1/memory>
#include <string>

class Person
{
    private:
    class PersonImpl;
    std::tr1::shared_ptr<PersonImpl> pImpl;

    public:
    Person(const std::string& name, int age=0);

    ~Person();

    const std::string& get_name() const;

    int get_age() const;
};

#endif

个人.cc

#include <string>
#include "person.hh"

class Person::PersonImpl
{
    public:
    std::string name;
    int age;

    PersonImpl(const std::string& n, int a) : name(n), age(a) {}
};

Person::Person(const std::string& name, int age) : pImpl(new PersonImpl(name, age)) {}

Person::~Person() {}

const std::string& Person::get_name() const { return pImpl->name; }

int Person::get_age() const { return pImpl->age; }

主文件

#include <iostream>
#include "person.hh"

int main()
{   
    const std::string name = "foo";
    Person p(name, 50);

    return 0;
}

除了代码错误之外,您能否就我模仿“pimpl”习语所采取的方法提出建议?这符合吗?

4

3 回答 3

4

问题似乎是由于您的person.cc文件没有被链接到。您可能需要调整项目配置来解决这个问题。

除了代码错误之外,您能否就我模仿“pimpl”习语所采取的方法提出建议?这符合吗?

我建议使用unique_ptr而不是shared_ptr,因为PersonImpl实现对象由Person对象专有:

class Person
{
private:
    class PersonImpl;
    std::tr1::unique_ptr<PersonImpl> pImpl;
//            ^^^^^^^^^^
    // ...
};

除此之外,您应该使用构造函数初始化列表来初始化pImpl数据成员:

Person::Person(const std::string& name, int age)
    : pImpl(new PersonImpl(name, age))
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
}
于 2013-05-20T13:20:02.097 回答
3

您需要使用这两个源文件进行构建。这可以通过将两个源文件放在命令行上来完成:

$ g++ -Wall -g main.cc person.cc

或者通过将它们一一编译为目标文件,然后将它们链接在一起

$ g++ -Wall -g main.cc -c
$ g++ -Wall -g person.cc -c
$ g++ main.o person.o

-c选项告诉 GCC 创建一个目标文件而不是尝试链接。-Wall启用更多警告,这总是一个好主意(它们可以指示一些意外行为),并-g告诉 GCC 生成调试信息(在调试时很好,尤其是在需要调试器时,因为调试信息包括符号名称)。

于 2013-05-20T13:19:33.437 回答
3

您收到链接器错误,而不是编译错误。链接时,您必须列出所有程序的源文件:

g++ main.cc person.cc

或者,仅编译,使用-c

g++ -c main.cc

编辑

此外,您Person的构造函数是错误的。你把pImpl它当作一个函数,我假设你想初始化它。您需要为此使用 mem-initialiser-list 语法:

Person::Person(const std::string& name, int age)
    : pImpl(new PersonImpl(name, age));
{}
于 2013-05-20T13:21:07.393 回答