unique_ptrs和转换指针和向量

时间:2015-07-17 16:28:44

标签: c++ c++11 vector unique-ptr

我创建了一个抽象类,然后创建了继承此抽象类的子类。

  class A{
       public:
       virtual A* clone() const = 0;
       virtual A* create() const = 0;
       ~virtual A(){};
       // etc.

  };

子课程

     class B: public A{};
     class C: public A{};
然后,我使用子类指针隐式转换为main函数中的基类指针。

     int main(){

     B* pB = new B();
     C* pC = new C();

     A* pA = pB;     //converting a pointer to A, to a pointer to B
     A* pAA = pC;    //converting a pointer to A, to a pointer to C

我现在可以使用类型A的指针填充这些类的向量,并通过多态访问子类。

    vector<A*> Pntr;

但是我希望每个子类都对自己的内存释放负责。我知道我可以使用独特的指针。问题是如何实现这一点。

如果我这样编码:

    pA = unique_ptr<A>(pB);
    pAA = unique_ptr<A>(pC);

然后我填充这样的矢量:

    vector<unique_ptr<A>>Pointers;
    Pointers.push_back(move(pA));
    Pointers.push_back(move(pAA));

不确定这是否会奏效。我也很困惑,当向量超出范围时,实际上会被销毁。将转换的指针pA和pAA简单地设置为NULL还是将类对象销毁 - 这是我的初衷。需要一些清晰度。

1 个答案:

答案 0 :(得分:1)

为什么不尝试这样做?

下面的示例提供了一种方法,您可以在其中创建Foo(您的抽象基类)和两个实现该接口的派生类(在本例中为Barstd::unique_ptr<Interface>)。

然后,您可以创建一个emplace_back容器(指向抽象基类的唯一指针),并使用各种方法和辅助函数填充它:std::make_unique push_back,{{1} } std::move,等等。

运行示例后,您会注意到析构函数会被自动调用 - 这是std::unique_ptr的美丽。

#include <cassert>
#include <memory>
#include <vector>
#include <iostream>

class Interface {
 public:
  virtual ~Interface() {
    std::cout << "Destroying object" << std::endl;
  }
  virtual void Method() const = 0;
};

class Foo // Foo "implements" or "offers access to" the Interface
    : public Interface {
 public:
  void Method() const override { // here we override Interface::Method
    std::cout << "Foo::Method" << std::endl;
  }
};

class Bar // Bar "implements" or "offers access to" the Interface
    : public Interface {
 public:
  void Method() const override { // here we override Interface::Method
    std::cout << "Bar::Method" << std::endl;
  }
};


int main() {
  // declare
  std::vector<std::unique_ptr<Interface>> objects;

  // populate
  objects.emplace_back(std::make_unique<Foo>());
  objects.emplace_back(std::make_unique<Bar>());
  objects.emplace_back(std::make_unique<Foo>());

  // another way to populate
  std::unique_ptr<Foo> pfoo(new Foo);
  objects.push_back(std::move(pfoo));

  // but be careful... pfoo now points to nullptr because you
  // moved ("transfered control of") the pointer to the
  // vector; pfoo no longer owns it (so it owns nothing; it is a
  // nullptr)
  assert(pfoo == nullptr);

  // you can iterate over all members by REFERENCE (otherwise you
  // would need to make copies, and you cannot copy a unique_ptr)
  for(const auto & pobject : objects) {
    pobject->Method();
  }

  // at exit you should see the calls to the destructor

  return 0;

}

编译并运行:

$ g++ example.com -std=c++14 -Wall -Wextra
$ ./a.out
Foo::Method
Bar::Method
Foo::Method
Foo::Method
Destroying object
Destroying object
Destroying object
Destroying object