2

这是一个非常愚蠢的错误,但我不知道这里发生了什么。

有很多 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:非法间接。

谢谢。

4

2 回答 2

10

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;
}
于 2010-10-21T09:05:49.820 回答
0

顺便说一句,将 boost::scoped_ptr 用于 pImpl 可能会遇到问题,因为您的 pImpl 是前向声明的,并且您可能会发现该类需要完全可见才能调用 scoped_ptr 的析构函数(这会删除底层)。

一些编译器允许您通过将析构函数的主体放在类可见的编译单元(.cpp 文件)中来解决此问题。

最简单的解决方案是,如果你的析构函数无论如何都必须实现,你也可以只使用原始指针并让你的析构函数删除它。如果您想使用 boost 中的某些东西来帮助您,请从 boost::noncopyable 派生您的外部类。否则,请确保您正确处理复制构造和分配。

您可以将 shared_ptr 用于您的 pImpl。然后,您可以愉快地复制您的外部类,尽管它们共享相同的底层,除非您重载复制构造函数和赋值运算符以做其他事情。

于 2010-10-21T09:24:28.387 回答