shared_ptr和this-pointer

时间:2011-02-02 08:33:32

标签: c++ this this-pointer shared-ptr

好的,我开始使用共享指针并尽可能地传递共享指针。不再转换为原始指针。这种方法很有效,除了在这种特殊情况下:

假设我们有一个类也是另一个类的观察者,如下所示:

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'是一个原始指针,而不是一个共享指针。

我看到了解决这个问题的三种方法:

  • 找到一个将普通指针转换为共享指针的技巧(请参阅问题convert pointer to shared_ptr),但该问题的答案仅建议复制共享指针,而不是如何将指针实际转换为共享指针。
  • 将共享指针传递给我们自己的方法,如下所示:“myInstance-&gt; DoSomethingImportant(myInstance);”这似乎有点愚蠢。
  • 将观察者部分放入单独的类中。这看起来有点矫枉过正,可能会使课程更难理解。

这个问题很明显共享指针只是C ++的一个附加组件(我不认为你在C#(或一般的.Net)和Java等其他语言/环境中遇到同样的问题。) / p>

关于如何处理这种情况的任何其他建议或窍门?

4 个答案:

答案 0 :(得分:8)

您需要的可能是enable_shared_from_thisshared_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实现良好的观察者模式设计 库。我鼓励你去看看。

最诚挚的问候,
马尔钦