Проблемы с компиляцией кода pimpl idiom

Я пытался испытать идиому «прыщ», но я просто не могу заставить проклятую вещь скомпилироваться.

В 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

Это мой код:

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

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

Помимо ошибок в коде, не могли бы вы порекомендовать подход, который я использовал для имитации идиомы «прыщ»? Это соответствует этому?

1

Решение

Кажется, проблема связана с тем, что ваш person.cc файл не связан с. Возможно, вам придется изменить конфигурацию вашего проекта, чтобы это исправить.

Помимо ошибок в коде, не могли бы вы порекомендовать подход, который я использовал для имитации идиомы «прыщ»? Это соответствует этому?

Я бы предложил использовать 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))
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
}
4

Другие решения

Вы должны построить с и то и другое исходные файлы. Это можно сделать, просто поместив оба исходных файла в командную строку:

$ 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 генерировать отладочную информацию (хорошо при отладке, особенно если отладчик необходим, так как отладочная информация включает в себя имена символов).

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));
{}
3
По вопросам рекламы [email protected]