Пимпл не работает - PullRequest
       4

Пимпл не работает

2 голосов
/ 21 октября 2010

Это очень грубая ошибка, но я не знаю, что здесь происходит.

Существует множество примеров pimpl, но я не понимаю, почему это не работает (это был один или несколько примеров, но я не вижу разницы).

У меня есть очень простой пример Pimpl, но он не будет работать.

// Foo.hpp
#include <boost/scoped_ptr.hpp>

class Foo
{
 struct Bar;
 //boost::scoped_ptr<Bar> pImpl;
 Bar* pImpl;

public:
 Foo();
 ~Foo() {}

 int returnValue();

private:

};

и

// Foo.cpp
#include "foo.hpp"

struct Foo::Bar
{ 
 Bar() {}
 ~Bar() {}
 int value;
};

Foo::Foo() : pImpl(new Bar())
{
 pImpl->value = 7;
}

int Foo::returnValue() {
 return *pImpl->value;
}

Компиляция этого дает мне ошибку. C2100: недопустимое косвенное указание.

Спасибо.

Ответы [ 2 ]

10 голосов
/ 21 октября 2010

int returnValue() должна быть функцией-членом:

//  vvvvv
int Foo::returnValue() {
 return pImpl->value; // no need to dereference, value isn't a pointer
}

Вам необходимо определить ваш конструктор, конструктор копирования, оператор копирования и деструктор после реализациикласс был определен.(В противном случае неявный деструктор опасен, и scoped_ptr не позволит вам сделать это):

// Foo.hpp
#include <boost/scoped_ptr.hpp>

class Foo
{
    struct Bar;
    boost::scoped_ptr<Bar> pImpl;

public:
    Foo();
    ~Foo();

    int returnValue(); // could be const (so should be)

private:
    // just disable copying, like scoped_ptr
    Foo(const Foo&); // not defined
    Foo& operator=(const Foo&); // not defined
};

И:

// Foo.cpp
#include "foo.hpp"

struct Foo::Bar
{ 
    int value;
};

Foo::Foo() :
pImpl(new Bar())
{
    pImpl->value = 7;
}

Foo::~Foo()
{
    // okay, Bar defined at this point; scoped_ptr can work
}

int Foo::returnValue()
{
    return pImpl->value;
}
0 голосов
/ 21 октября 2010

Кроме того, у вас может возникнуть проблема с использованием boost :: scoped_ptr для pImpl, потому что ваш pImpl объявлен заранее, и вы можете обнаружить, что класс должен быть полностью видимым, чтобы вызвать деструктор scoped_ptr (который удаляет базовый элемент) .

Некоторые компиляторы позволят вам обойти эту проблему, поместив тело вашего деструктора в модуль компиляции (файл .cpp), где виден класс.

Самое простое решение состоит в том, что если ваш деструктор должен быть реализован так или иначе, вы можете просто использовать необработанный указатель и удалить его деструктором. И если вы хотите использовать что-то из boost, чтобы помочь вам, выведите свой внешний класс из boost :: noncopyable. В противном случае убедитесь, что вы правильно обрабатываете конструкцию и назначение копирования.

Вы можете использовать shared_ptr для вашего pImpl. Затем вы можете счастливо скопировать свой внешний класс, хотя они совместно используют один и тот же базовый класс, если вы не перегружаете конструктор копирования и оператор присваивания, чтобы сделать иначе.

...