使用基类而不是基指针来处理派生类

时间:2016-05-01 11:49:24

标签: c++ inheritance

我有一个像这样的基础抽象类;

class X {
public:
    virtual ~X(){}
    virtual doSomething() = 0;
};

然后我用Y,Z等几个类来实现它,每个类都有自己的构造函数,析构函数和doSomething实现。在我的主要功能中,我做了;

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()
    }
}

这会按预期调用各自的doSomething实现。但我的问题是我使用指针抽象类来通过其基类操作派生类的层次结构。这迫使我使用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时会自动调用析构函数。我知道我不能创建一个抽象类的成员,但使用指针来实现这一切似乎很奇怪。当然必须有一种方法可以在没有指针和新删除的情况下执行此操作。如果有人向我展示了最佳实践,那就太好了。

2 个答案:

答案 0 :(得分:5)

您想使用适当的智能指针:

std::vector<std::unique_ptr<X>> v;

v.push_back(std::make_unique<Y>());
v.push_back(std::make_unique<Z>());

// all done

(当然还有动态分配,因为在没有运行时间接的情况下你无法管理无限数量的无约束类型,但你不应该手动思考关于任何动态管理。系统可以为您完成所有工作。)

答案 1 :(得分:2)

尽管Kerrek SB发布了很好的答案,但是OP要求解决方案(让我说)new - 免费,并且值得为此添加一个答案。

您可以使用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 s,您将不会遇到此问题,正如Kerrek SB在其他答案中所建议的那样。