临时派生对象的初始化列表

时间:2016-10-17 20:29:20

标签: c++11

假设我有一个类A和两个派生类BC,例如:

#include <iostream>
#include <list>
#include <string>

using namespace std;

class A {
public:
  virtual void poke() const = 0;
  virtual ~A() {};
};

class B : public A {
  string _response;
public:
  B(const string& response) : _response(response) {}
  void poke () const {
    cout << _response << endl;
  }
};

class C : public A {
  string _response;
public:
  C(const string& response) : _response(response) {}
  void poke () const {
    cout << "Well, " << _response << endl;
  }
};

我可以使用以下初始化列表std::list以某种方式初始化{B("Me"), C("and you")},以便当我遍历列表并调用poke()时(即不发生切片)多态性有效吗?我想我需要定义一个std::list<Smth>,其中Smth接受临时对象,有一个复制构造函数,它确实在内部移动语义(因为初始化列表似乎在进行复制而不是移动),并支持智能指针所以我可以使用it进行迭代并执行(*it)->poke()。为了清楚起见,我希望能够写下:

list<Smth> test {B("Me"), C("and you")};
for(auto it = test.begin(); it != test.end(); it++) {
  (*it)->poke();
}

我试图找到一个简单的解决方案,但我到了我的程序编译但生成运行时错误的点,所以我放弃了那个点......也许某种程度上从临时对象中创建一个独特的指针?或者我能以某种方式使用&&吗?

2 个答案:

答案 0 :(得分:1)

对于多态,您需要引用或指针。一旦句子结束,两者都将变为悬空,因为即使你以某种方式将这些对象绑定到它们,你也将它们绑定到临时对象。 通常的解决方案是动态分配和创建对象并使用指针保存它们。这意味着类似下面的内容(我也将循环更改为C ++ 11样式,而不是直接使用迭代器):

std::list<std::unique_ptr<A>> test {
    std::make_unique<B>("Me"), std::make_unique<C>("and you")};
for(const auto& p : test) {
    p->poke();
}

答案 1 :(得分:0)

好吧,如果我愿意额外复制BC并使用shared_ptr代替unique_ptr,那么以下示例有效(我是不是说它是好的编程风格,但它确实显示了使用初始化列表方便表示法的成本):

#include <iostream>
#include <list>
#include <memory>
#include <string>

using namespace std;

class A {
public:
  virtual void poke() const = 0;
  virtual ~A() {}
};

class B : public A {
  string _response;
public:
  B(const string& response) : _response(response) {}
  void poke () const {
    cout << _response << endl;
  }
  operator shared_ptr<A>() {
    return make_shared<B>(*this);
  }
};

class C : public A {
  string _response;
public:
  C(const string& response) : _response(response) {}
  void poke () const {
    cout << "Well, " << _response << endl;
  }
  operator shared_ptr<A>() {
    return make_shared<C>(*this);
  }
};

int main() {
  list<shared_ptr<A>> test {B("Me"), C("and you")};

  for(const auto& it : test) {
    it->poke();
  }
}