好的,我开始使用共享指针并尽可能地传递共享指针。不再转换为原始指针。这种方法很有效,除了在这种特殊情况下:
假设我们有一个类也是另一个类的观察者,如下所示:
class MyClass : public IObserver
{
public:
MyClass (std::shared_ptr<SomeOtherClass> otherClass);
void DoSomethingImportant();
private:
std::shared_ptr<SomeOtherClass> m_otherClass;
};
这个类在我的应用程序中使用如下:
std::shared_ptr<MyClass> myInstance(new MyClass(otherInstance));
...
myInstance->DoSomethingImportant();
MyClass获取另一个类的共享指针,并将其存储在m_otherClass数据成员中。 在DoSomethingImportant方法中,MyClass实例执行许多重要的操作,包括将自己注册为m_otherClass上的观察者,如下所示:
m_otherClass-&GT; registerObserver(本);
问题是registerObserver方法定义如下:
void registerObserver(std :: shared_ptr observer);
它需要一个共享指针,但'this'是一个原始指针,而不是一个共享指针。
我看到了解决这个问题的三种方法:
这个问题很明显共享指针只是C ++的一个附加组件(我不认为你在C#(或一般的.Net)和Java等其他语言/环境中遇到同样的问题。) / p>
关于如何处理这种情况的任何其他建议或窍门?
答案 0 :(得分:8)
您需要的可能是enable_shared_from_this
和shared_from_this
设施。文档为here
请注意,在构造函数完全完成且对象已由另一个shared_from_this
拥有之前,您无法使用shared_ptr
。
struct test : boost::enabled_shared_from_this<test>
{
test() {
// shared_from_this(this); // error, still not owned by another shared_ptr
}
boost::shared_ptr<test> shared() {
return shared_from_this(this);
}
};
int main() {
test * t = new test;
// boost::shared_ptr<test> p = t->shared(); // error, not yet owned by other shared_ptr
boost::shared_ptr<test> owner( t );
boost::shared_ptr<test> p = t->shared(); // [*] ok, "owner" owns the object
}
[*]这部分示例很愚蠢,您可以将所有者复制到p中,而不是调用该方法。只是在shared_from_this
方法中调用test
时可以注意到它。
答案 1 :(得分:4)
对于观察者模式,观察对象不占用观察者的所有权,为什么不使用原始指针?观察者的生命周期应由观察者自己控制。
通过使用enable_shared_from_this,可以为观察者及其观察对象引入循环依赖性。这意味着如果不明确删除,资源将永远不会被释放。
答案 2 :(得分:0)
如何将构造函数设为私有并具有如下静态构造方法:
class MyClass : public IObserver
{
public:
static std::shared_ptr<MyClass> createObserver(std::shared_ptr<SomeOtherClass> otherClass);
void DoSomethingImportant();
private:
MyClass (std::shared_ptr<SomeOtherClass> otherClass);
std::shared_ptr<SomeOtherClass> m_otherClass;
};
然后你可以在静态方法中干净地实例化观察者,而不必担心这个指针。
答案 3 :(得分:0)
您可以将注册步骤移到单独的方法中吗? :
shared_ptr<SomeOtherClass> other(new SomeOtherClass());
shared_ptr<MyClass> my(new MyClass());
// register myself to the observer
other->registerObserver(my);
my->DoSomethingImportant();
可以使用boost :: signal和boost :: bind实现良好的观察者模式设计 库。我鼓励你去看看。
最诚挚的问候,
马尔钦