但那是我想要实现的目标吗?
关键是如果没有更清晰的描述,我们就无法判断。这听起来很简单:信号专门用于解耦调用者和被调用者。
所以让我为你编造你的"dummycode"。我将回避您在该行中显示的巨大的类型过度复杂性:
boost::signals2::connection tria_signal =
/*...*/.connect(boost::signals2::signal<void()>::slot_type(
&Solid::call_this_function, pointer_M.get())
.track(pointer_M));
槽的整个想法是它们使用类型擦除来概括可调用对象。只需以任何兼容的形式提供您的可调用对象,然后让库推断出神秘的实现类型。
Live On Coliru
#include <boost/signals2.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
struct OtherClass {
OtherClass(...) {}
boost::signals2::signal<void()> tria;
void test() {
if (!tria.empty())
tria();
}
};
struct Solid {
boost::shared_ptr<OtherClass> pointer_M;
Solid() {
pointer_M = boost::make_shared<OtherClass>(1,2,3);
auto tria_signal = pointer_M->tria.connect(
boost::bind(&Solid::call_this_function, this));
}
private:
void call_this_function() {
std::cout << "Solid was here" << std::endl;
};
};
int main() {
Solid s;
s.pointer_M->test();
}
打印
Solid was here
水晶球:我们能猜出问题吗?
也许我们可以猜到问题所在:看起来您正在努力跟踪pointer_M 指向的对象的生命周期。这没什么用,因为OtherClass 首先拥有信号,这意味着当OtherClass 消失时,所有连接都会断开。
正确的生命周期管理
您可能想要的是在Solid 对象的生命周期结束时断开连接,不是 OtherClass。一般来说,我建议在这里使用scoped_connection:
Live On Coliru
#include <boost/signals2.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
struct OtherClass {
OtherClass(...) {}
boost::signals2::signal<void()> tria;
void test() {
if (!tria.empty())
tria();
}
};
struct Solid {
boost::shared_ptr<OtherClass> pointer_M;
Solid() {
pointer_M = boost::make_shared<OtherClass>(1,2,3);
tria_signal = pointer_M->tria.connect(
boost::bind(&Solid::call_this_function, this));
}
private:
boost::signals2::scoped_connection tria_signal;
void call_this_function() {
std::cout << "Solid was here" << std::endl;
};
};
int main() {
boost::shared_ptr<OtherClass> keep;
{
Solid s;
std::cout << "Testing once:" << std::endl;
s.pointer_M->test();
keep = s.pointer_M; // keep the OtherClass alive
} // destructs Solid s
std::cout << "Testing again:" << std::endl;
keep->test(); // no longer connected, due to scoped_connection
}
打印
Testing once:
Solid was here
Testing again:
简化
在您的情况下,OtherClass 已经由 Solid 拥有(至少它是创建的)。似乎根本不需要共享指针:
Live On Coliru
#include <boost/signals2.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
struct OtherClass {
OtherClass(...) {}
boost::signals2::signal<void()> tria;
void test() {
if (!tria.empty())
tria();
}
};
struct Solid {
Solid() : oc_M(1,2,3) {
tria_signal = oc_M.tria.connect(
boost::bind(&Solid::call_this_function, this));
}
void test() { oc_M.test(); }
private:
OtherClass oc_M;
boost::signals2::scoped_connection tria_signal;
void call_this_function() {
std::cout << "Solid was here" << std::endl;
};
};
int main() {
Solid s;
s.test();
}
因为成员是按照声明的相反顺序销毁的,所以这是完全安全的。
建筑航天
如果您知道自己在做什么,并且 pointer_M 实际上需要共享,那么您可能想要跟踪 that 指针。您可能应该考虑制作Solid 和enable_shared_from_this。如果您想成为真正的“企业级工程师™”,您也许可以使用别名构造函数做一些花哨的事情:What is shared_ptr's aliasing constructor for?