【问题标题】:How do non-intrusive smart pointers behave with respect to inheritance and multiple inheritance?非侵入式智能指针在继承和多重继承方面的表现如何?
【发布时间】:2010-10-13 15:34:13
【问题描述】:

我正在使用 C++。 C++0x 使用 Visual Studio 2010 是正确的。

假设我有一个类 Z。为了让我的应用程序更安全地使用指向该类的指针,我可以始终使用智能指针(共享指针、弱指针)。

现在这个类 Z 继承自一个类 X。我的应用程序的某些部分将使用指向类 X 的指针,其他部分将使用指向类 Z 的指针。

  • 我还能使用智能指针吗?
  • 如果我有一些指向 X 和其他指向 Z 的共享指针仍然有效吗?是否保证销毁最后一个指向实例的共享指针(不管是std::shared_ptr<X>还是std::shared_ptr<Z>)会删除实例?我确定如果我删除std::shared_ptr<X>,只要有另一个std::shared_ptr<Y>,实例就会保留?

现在假设我使用多重继承,其中 Z 继承自类 X 和 Y。 我的应用程序的某些部分可以使用std::shared_ptr<X>,其他部分可以使用std::shared_ptr<Y>,其他部分可以使用std::shared_ptr<Z>。

  • 我还能这样使用共享指针吗?
  • 是否仍然保证只有最后一个智能指针(无论它指向 X、Y 还是 Z)删除实例?

顺便说一句,我怎样才能安全地将一个智能指针转换为另一个,例如将std::shared_ptr<Z> 转换为std::shared_ptr<X>?这行得通吗?这允许吗?

请注意,我明确引用了非侵入式指针(如 C++0x 中的新 std::shared_ptr 和 std::weak_ptr)。当使用侵入式指针时(如在 Boost 中),它可能会起作用,因为实例本身负责保持计数器。

【问题讨论】:

    标签: visual-studio-2010 c++11 smart-pointers


    【解决方案1】:

    是的,标准 §20.9.11.2.10 [util.smartptr.shared.cast] 支持。

    你需要的工具是:

    • std::static_pointer_cast<>()
    • std::dynamic_pointer_cast<>()

    它们与 C++03 对应部分 static_cast<>() 和 dynamic_cast<>() 具有相同的语义。一个区别是它们仅适用于std::shared_ptrs。只是为了冗长,他们会做你期望的事情,并正确地在原始和新演员 shared_ptrs 之间共享引用计数。

    struct X { virtual ~X(){} };
    struct Y : public X {};
    struct Z : public X {};
    
    int main()
    {
       {
          //C++03
          X* x = new Z;
          Z* z = dynamic_cast<Z*>(x);
          assert(z);
          x = new Y;
          z = dynamic_cast<Z*>(x);
          assert(!z);
          z = static_cast<Z*>(x);
          assert(z); //EVIL!!!
       }
    
       {
          //C++0x
          std::shared_ptr<X> x{new Z};
          std::shared_ptr<Z> z{std::dynamic_pointer_cast<Z>(x)};
          assert(z);
          x = std::make_shared<Y>();
          z = std::dynamic_pointer_cast<Z>(x);
          assert(!z);
          z = std::static_pointer_cast<Z>(x);
          assert(z); //EVIL!!!
    
          // reference counts work as expected.
          std::shared_ptr<Y> y{std::static_pointer_cast<Y>(x)};
          assert(y);
    
          std::weak_ptr<Y> w{y};
          assert(w.expired());
    
          y.reset();
          assert(w.expired());
    
          x.reset();
          assert(!w.expired());      
       }
       {
          //s'more nice shared_ptr features
          auto z = std::make_shared<X>();
          std::shared_ptr<X> x{z};
          assert( z == x );
          x = z; //assignment also works.
       }
    }
    

    【讨论】:

    • 哇从没听说过这个... O__o 除了(不消化的)草稿之外,我在 C++0x 上可以找到的任何资源中都没有提到这个...
    • 在我查到之前,我不确定演员在哪里。然而,我确实强烈怀疑它们在那里,因为它们是原始 Boost.Smartptr 库的一部分。
    • 请去掉内置强制转换运算符前面的“std::”。此外,这种类型的动态转换需要多态类。您的示例类不是多态的。
    • 已修复,或许 SO 应该可以选择通过 edge online 过滤代码样本进行验证。
    猜你喜欢
    • 1970-01-01
    • 2012-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-30
    相关资源
    最近更新 更多