假设我有一个类A
和两个派生类B
和C
,例如:
#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();
}
我试图找到一个简单的解决方案,但我到了我的程序编译但生成运行时错误的点,所以我放弃了那个点......也许某种程度上从临时对象中创建一个独特的指针?或者我能以某种方式使用&&
吗?
答案 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)
好吧,如果我愿意额外复制B
和C
并使用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();
}
}