1

次の .h ファイルを検討してください。

#ifndef COM_H_
#define COM_H_

#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <map>

class B;

class A : public boost::enable_shared_from_this<A>{
public:
    A(){}
    ~A(){}

    void Init();

    boost::shared_ptr<B> b_ptr_;
};

class B : public boost::enable_shared_from_this<B>{
public:

    B(){}
    B(boost::shared_ptr<A> a_ptr);
    B(int j, boost::shared_ptr<A> a_ptr);
    ~B(){}

    void Init();
    void Init(boost::shared_ptr<A> a_ptr);
    void Init(int j, boost::shared_ptr<A> a_ptr);

    std::string b;
    boost::shared_ptr<A> a_ptr_;
};
#endif /* COM_H_ */

および .cc ファイル:

#include "com.h"

void A::Init() {

    // Case 1 not working
    // boost::shared_ptr<B> b1(new B(shared_from_this()));
    // b1->Init();

    // Case 2 working
    boost::shared_ptr<B> b2(new B());
    b2->Init(shared_from_this());
}

B::B(boost::shared_ptr<A> a_ptr) {
    B(2, a_ptr);
}

B::B(int j, boost::shared_ptr<A> a_ptr) {
    a_ptr_ = a_ptr;
    b = "b";
}

void B::Init() {
    a_ptr_->b_ptr_ = shared_from_this();
}

void B::Init(boost::shared_ptr<A> a_ptr) {
    Init(2, a_ptr);
}

void B::Init(int j, boost::shared_ptr<A> a_ptr) {

    a_ptr_ = a_ptr;
    b = "b";
    a_ptr_->b_ptr_ = shared_from_this();
}

主に:

#include "com.h"
#include <iostream>
int main() {

    boost::shared_ptr<A> a(new A());
    a->Init();

    std::cout << a->b_ptr_->b << std::endl;

    return 0;
}

boost::shared_ptr をコンストラクターに渡してから、同じポインターを引数として別の (オーバーロードされた) コンストラクターを呼び出すと、shared_ptr が指すオブジェクトが失われ、エラーが発生します。

「boost::exception_detail::clone_impl」のインスタンスをスローした後に呼び出される終了

' what(): tr1::bad_weak_ptr

投げられます。同じ方法で 2 つのオーバーロードされた関数 (Init) を呼び出した場合、同じことは起こりません。

誰か説明してくれませんか?

4

1 に答える 1

0

問題は、B の構築中に shared_from_this() を呼び出していることです。これは、B への共有ポインターがその時点で初期化されていないため禁止されています。

具体的には、このコンストラクターは、呼び出しているものです。

B::B(boost::shared_ptr<A> a_ptr) {
    Init(2, a_ptr);  // runtime error -- Init(...) calls shared_from_this!
}

回答パート 2:

あなたは別の言語に慣れていると思います:) C++では、あなたがしようとしている方法で別のコンストラクターを呼び出すことはできません。この線

B(2, a_ptr);

あなたが考えていることをしていません-それがしているのは、すぐに破棄される一時的な B オブジェクトを構築することだけです。他のコンストラクターは呼び出されません。したがって、デフォルトで構築された a_ptr_ メンバーがまだある B になってしまいます。

コンパイラがサポートしている場合、C++-11 には委譲コンストラクタがあり、次のようになります。

B(shared_ptr<A> a_ptr) : B(2, a_ptr) {...}

... そうでなければ、別の関数を宣言し、両方のコンストラクターにそれを呼び出させる必要があります。

于 2012-09-18T14:03:19.953 に答える