2013-05-20 2 views
1

'pimpl'관용어로 가려고했지만 나는 컴파일 할 수 없습니다.pimpl 관용구 컴파일시 문제

g의 ++ v의 리눅스 민트에

4.6.3 나는 다음과 같은 오류 얻을 :.

#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 

person.cc

person.hh : 이것은 내 코드

$ 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 

입니다

#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; } 

main.cc

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

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

    return 0; 
} 

코드 실수는 별도로 'pimpl'관용어를 모방 한 방법에 대해 조언 해 주실 수 있습니까? 이것에 부합합니까?

답변

4

person.cc 파일이 연결되어 있지 않기 때문에 문제가 발생한 것 같습니다.이를 해결하려면 프로젝트 구성을 조정해야 할 수 있습니다. 이 외에도에서

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

, 당신은 constructor initialization lists의 사용은 pImpl을 initalize 수 있도록해야 다음 PersonImpl 구현 객체가 Person 객체에 의해 독점적으로 소유하고 있기 때문에

Apart from the code mistakes, could you please advise on the approach I've taken to mimicking a 'pimpl' idiom? Does this conform to it?

나는, shared_ptr보다는 unique_ptr을 사용하는 것이 좋습니다 것입니다 데이터 멤버 :

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

unique_ptr 제안과이 특정 사례에 대한 초기화 프로그램 목록을 보내 주셔서 감사합니다. 링크 문제를 해결하면 코드에 몇 가지 다른 문제가 있음을 발견했습니다. – Nobilis

+1

@Nobilis : 다행스럽게도 도움이되었습니다. :) –

3

소스 파일로 빌드해야합니다. 이 중 하나를 수행 할 수 있습니다 단지 명령 줄에서 모두 소스 파일을 퍼팅 할 수 :

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

또는 함께 -c 옵션을 알려줍니다

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

그들을 연결 한 후 객체 파일을 하나씩 컴파일에 의해 GCC는 링크를 시도하는 대신 오브젝트 파일을 생성합니다. -Wall은 항상 좋은 생각 인 좋은 경고를 제공하며 (의도하지 않은 동작을 나타낼 수 있음) -g은 GCC에 디버그 정보를 생성하도록 지시합니다 (특히 디버그 정보가 심볼 이름을 포함하므로 디버거가 필요한 경우).

+0

감사를 다룰 때, 나는 일반적으로 나는 모든 포함되어 있는지 확인 경비 포함 .cc 파일을 내 makefile에 넣었으나 명령 줄에서 인위적으로이 파일을 실행하려고했습니다. 얼마나 당황 스럽습니까? – Nobilis

3

당신은 getti입니다. 링커 오류가 아니라 컴파일 오류가 발생합니다.

g++ main.cc person.cc 

를 또는, 컴파일 만 -c 사용 : 링크 할 때, 당신은 당신의 프로그램의 소스 파일을 모두 나열해야

g++ -c main.cc 

편집 또한

, 당신은 Person 생성자가 잘못 .당신은 함수로 pImpl을 치료하고 있습니다, 당신이 그것을 생생하게하고 싶다고 가정합니다. 당신은이에 대한 MEM-initialiser리스트 구문을 사용해야합니다 내가 같은 초보자의 실수에 의해 잡힌 믿을 수 없어, 그것을위한

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

큰 프로젝트에서 초급 자의 실수입니다. 모든 소스 파일을 Makefile에 포함시키지 만 여기서 그 일을 잊어 버렸습니다. 또한 이니셜 라이저 목록 주석, 좋은 점에 대해 감사드립니다. – Nobilis