1

私は「ピンプル」イディオムを試してみましたが、コンパイルするための忌まわしきものを手に入れることができません。

Linux Mint で 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

これは私のコードです:

人.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

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

main.cc

#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_ptrPersonImplPerson

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

または、それらを 1 つずつオブジェクト ファイルにコンパイルしてから、それらをリンクします。

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

この-cオプションは、リンクを試行する代わりに、オブジェクト ファイルを作成するように GCC に指示します。-Wallより多くの警告を有効にしますが、これは常に良い考えであり (意図しない動作を示す可能性があります)、-gGCC にデバッグ情報を生成するように指示します (デバッグ中、特にデバッグ情報にシンボル名が含まれているため、デバッガーが必要な場合に適しています)。

于 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 に答える