代码之家  ›  专栏  ›  技术社区  ›  Patrick

非侵入式智能指针在继承和多重继承方面如何表现?

  •  5
  • Patrick  · 技术社区  · 14 年前

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

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

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

    现在假设我使用多重继承,其中Z继承自类X和类Y。 标准:共享的; ,其他 以及其他 标准::共享空间<Z>

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

    顺便说一下,我怎样才能安全地将一个智能指针投射到另一个指针上,例如cast 标准::共享空间<Z> 标准:共享的; ? 这有用吗?这是允许的吗?

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

    1 回复  |  直到 14 年前
        1
  •  6
  •   deft_code    14 年前

    是的,这是由标准,§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_ptr s、 为了详细起见,他们做了您期望的事情,并在原始和新的cast之间正确地共享了引用计数 shared_ptr s。

    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.
       }
    }