Рассмотрим следующий файл .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, теряется и ошибка
завершить вызов после броска экземпляра
«Повышение :: exception_detail :: clone_impl‘что (): tr1 :: bad_weak_ptr
брошен Этого не происходит при одинаковом вызове двух перегруженных функций (Init).
Может кто-нибудь, пожалуйста, объясните это?
Проблема в том, что вы вызываете shared_from_this () во время построения B, что запрещено, потому что общий указатель на 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, который немедленно уничтожается. Он не будет вызывать другой конструктор. Таким образом, вы получите B, который все еще имеет член a_ptr_, созданный по умолчанию.
C ++ — 11, если ваш компилятор поддерживает его, имеет делегирующие конструкторы, которые будут выглядеть так:
B(shared_ptr<A> a_ptr) : B(2, a_ptr) {...}
… В противном случае вы должны объявить другую функцию, и оба конструктора вызовут ее.
Других решений пока нет …