2

これは非常に厄介な間違いですが、ここで何が起こっているのかわかりません。

単純な例はたくさんありますが、なぜこれが機能しないのかわかりません(これは多かれ少なかれ例の1つでしたが、違いはわかりません)。

非常に単純な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

余談ですが、pImpl に boost::scoped_ptr を使用すると問題が発生する可能性があります。これは、pImpl が前方宣言されており、scoped_ptr のデストラクタ (基になるものを削除する) を呼び出すためにクラスを完全に可視にする必要がある場合があるためです。

一部のコンパイラでは、クラスが表示されるコンパイル ユニット (.cpp ファイル) にデストラクタの本体を配置することで、これを回避できます。

最も簡単な解決策は、とにかくデストラクタを実装する必要がある場合は、生のポインタを使用してデストラクタに削除させることです。また、boost の何かを使用して支援したい場合は、boost::noncopyable から外部クラスを派生させます。それ以外の場合は、コピー構築と代入を適切に処理するようにしてください。

pImpl に shared_ptr を使用できます。その後、コピー コンストラクターと代入演算子をオーバーロードして別の方法で実行しない限り、同じ基になるクラスを共有していても、外部クラスを問題なくコピーできます。

于 2010-10-21T09:24:28.387 に答える