我有一个像这样的基础抽象类;
class X {
public:
virtual ~X(){}
virtual doSomething() = 0;
};
然后我用几个类来实现这个,比如Y、Z等,每个类都有自己的构造函数、析构函数和do的实现。在我的主函数中,我这样做;
int main(){
std::vector<X *> v;
X *x1 = new Y();
X *x2 = new Z();
v.push_back(x1);
v.push_back(x2);
for(auto p : v){
p->doSomething()
}
}
这按预期调用了各自的do东西实现。但我的问题是,我正在使用指向抽象类的指针通过其基类来操作派生类的层次结构。这迫使我使用new在堆上创建实例,之后我必须手动删除它们。有没有办法做这样的事情;
int main(){
std::vector<X> v;
Y x1();
Z x2();
v.push_back(x1);
v.push_back(x2);
for(auto p : v){
p.doSomething()
}
}
所以当我离开main时,析构函数会被自动调用。我知道我不能创建抽象类的成员,但是使用指针来实现这一切似乎很奇怪。当然,一定有一种方法可以在没有指针和new-delete的情况下做到这一点。如果有人给我展示一下最佳实践,那就太好了。
您想使用适当的智能指针:
std::vector<std::unique_ptr<X>> v;
v.push_back(std::make_unique<Y>());
v.push_back(std::make_unique<Z>());
// all done
(当然仍然存在动态分配,因为如果没有运行时间接,您无法管理无限数量的无约束类型,但您永远不必手动考虑任何动态管理。类型系统可以为您完成所有工作。)
尽管Kerrek SB发布了很好的答案,但OP要求提供一个解决方案(让我说)new
-free,值得为此再添加一个答案。
您可以使用std::reference_wrapper
。
它遵循一个最小的工作示例:
#include<vector>
#include<functional>
#include<iostream>
class X {
public:
virtual ~X(){}
virtual void doSomething() = 0;
};
class Y: public X {
void doSomething() override {
std::cout << "Y" << std::endl;
}
};
class Z: public X {
void doSomething() override {
std::cout << "Z" << std::endl;
}
};
int main(){
std::vector<std::reference_wrapper<X>> v;
Y x1{};
Z x2{};
v.emplace_back(x1);
v.emplace_back(x2)
for(X &p : v){
p.doSomething();
}
}
请注意,在这种情况下,您必须保证存储对象的生命周期克服了向量之一。
如果您计划使用std::unique_ptr
,就不会有这个问题,正如Kerrek SB在另一个答案中所建议的那样。