Я пытался испытать идиому «прыщ», но я просто не могу заставить проклятую вещь скомпилироваться.
В 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;
}
Помимо ошибок в коде, не могли бы вы порекомендовать подход, который я использовал для имитации идиомы «прыщ»? Это соответствует этому?
Кажется, проблема связана с тем, что ваш 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))
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
}
Вы должны построить с и то и другое исходные файлы. Это можно сделать, просто поместив оба исходных файла в командную строку:
$ 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++ 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));
{}