C++ 编译pimpl习惯用法代码时出现的问题

C++ 编译pimpl习惯用法代码时出现的问题,c++,pimpl-idiom,C++,Pimpl Idiom,我一直在尝试一个“pimpl”的习惯用法,但我就是无法编译这个该死的东西 在LinuxMint上使用g++v。4.6.3我得到以下错误: $ 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::alloca

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

在LinuxMint上使用g++v。4.6.3我得到以下错误:

$ 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
$g++main.cc
/tmp/ccXQ9X9O.o:在函数“main”中:
main.cc:(.text+0xd7):对“Person::Person(std::basic_string const&,int)”的未定义引用
collect2:ld返回了1个退出状态
这是我的代码:

person.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
\ifndef PERSON\u HH
#定义人
#包括
#包括
班主任
{
私人:
阶级人格;
std::tr1::shared_ptr pImpl;
公众:
Person(const std::string&name,int age=0);
~Person();
const std::string&get_name()const;
int get_age()常量;
};
#恩迪夫
person.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; }
#包括
#包括“person.hh”
类Person::PersonImpl
{
公众:
std::字符串名;
智力年龄;
PersonImpl(const std::string&n,inta):姓名(n),年龄(a){
};
Person::Person(const std::string&name,int age):pImpl(新PersonImpl(name,age)){}
人物::~Person(){}
const std::string&Person::get_name()const{return pImpl->name;}
int Person::get_age()const{return pImpl->age;}
main.cc

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

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

    return 0;
}
#包括
#包括“person.hh”
int main()
{   
const std::string name=“foo”;
p人(姓名,50);
返回0;
}
除了代码错误,你能告诉我模仿“pimpl”习惯用法的方法吗?这符合它吗?

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

$ 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生成调试信息(在调试时很好,特别是当调试信息包括符号名时需要调试器)。

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

$ 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生成调试信息(在调试时很好,特别是当调试信息包括符号名时需要调试器时).

问题似乎是由于没有链接到您的
person.cc
文件。您可能需要调整项目配置以修复此问题

除了代码错误,你能告诉我模仿“pimpl”习惯用法的方法吗?这符合吗

我建议使用
unique\u ptr
而不是
shared\u ptr
,因为
PersonImpl
实现对象完全由
Person
对象拥有:

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

问题似乎是由于您的
person.cc
文件未链接到。您可能需要调整项目配置以修复此问题

除了代码错误,你能告诉我模仿“pimpl”习惯用法的方法吗?这符合吗

我建议使用
unique\u ptr
而不是
shared\u ptr
,因为
PersonImpl
实现对象完全由
Person
对象拥有:

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

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

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));
{}

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

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));
{}

感谢您对此特定案例的独特建议和初始化列表,在解决链接问题后,我发现我的代码还存在一些其他问题。@Nobilis:很高兴它有所帮助:)感谢您对此特定案例的独特建议和初始化列表,在解决了链接问题后,我发现我的代码还存在一些其他问题。@Nobilis:很高兴它有帮助:)