c++ - 继承:包含派生类实例的基类模板容器

标签 c++ oop templates inheritance

我按以下方式组织了三个类(class)。 Foo是模板类,Bar派生自FooDoo派生自Foo 也是。它们都实现了一个 doX() 成员函数,该成员函数在 Foo 中定义为虚函数。

我需要一个包含 BarDoo 对象的 vector (或任何其他容器)。例如,一个名为 vec 的两个对象的 vector ,第一个元素应该是一个 Doo,第二个应该是一个 Bar。当我调用 vec[0].doX() 时,应该调用 Doo::doX()。定义指向 Foo 对象的指针 vector ,完成这项工作。但我不确定实例实际存储在哪里。如果我将指针指向对象,分配的内存可能会在离开创建对象的范围后释放。

我准备了一个最小的工作示例来说明问题:

#include <iostream>
#include <vector>

using namespace std;

template <typename T>
class Foo
{
public:
    virtual void doX(){cout<<"doX from Foo"<<endl;}
};

template <typename T>
class Bar : public Foo<T>
{
public:
    void doX(){cout<<"doX from Bar"<<endl;}
    void g(string const &input);    // some test function may be used in doX
    int x;                          // some test data may be used in doX
};

template <typename T>
class Doo : public Foo<T>
{
public:
    void doX(){cout<<"doX from Doo"<<endl;}
};

void doSomething(vector<Foo<int>* >& target)
{
    Foo<int> X;
    // do some extreme job to generate X
    target.push_back(&X); // ==> This is problematic
}

int main()
{
    Foo<int> f;
    Bar<int> b;
    Doo<int> d;
    vector<Foo<int> > v;
    v.push_back(f);
    v.push_back(b);
    v.push_back(d);
    v[0].doX();             // doX from Foo
    v[1].doX();             // doX from Foo
    v[2].doX();             // doX from Foo
    vector<Foo<int>*> v2;
    v2.push_back(&f);       // here is no problem, but if `f` is generated inside
                            // a function that receives a reference to `vec` there
                            // will be problems
    doSomething(v2);        // This is problematic
    v2.push_back(&b);
    v2.push_back(&d);
    v2[0]->doX();           // doX from Foo
    v2[1]->doX();           // doX from Foo but dangerous! May crash
    v2[2]->doX();           // doX from Bar
    v2[3]->doX();           // doX from Doo

    return 0;
}

最佳答案

您已正确识别问题。您必须确保 vector 中的指针指向的实例至少与 vector 本身一样长。您可以存储指向动态分配对象的指针,这意味着您负责控制它们的生命周期。这可以通过存储指向使用 new 创建的实例的指针来实现,或者更好的是,smart pointers其中。

void addElements(vector<Foo<int>* >& target)
{
    target.push_back(new Bar<int>());
    target.push_back(new Doo<int>());
}

在上面的示例中,您必须确保在完成后删除 vector 的元素(通常在 vector 超出范围之前)。

带有 std::unique_ptrs 的 C++11 示例:

std::vector<std::unique_ptr<Foo<int>> v;
v.push_back(std::unique_ptr<Foo<int>>(new Bar<int>()); // moves the unique_ptr
v.push_back(std::unique_ptr<Foo<int>>(new Doo<int>()); // moves the unique_ptr
v.emplace_back(new Bar<int>()); // constructs the unique_ptr in place

关于c++ - 继承:包含派生类实例的基类模板容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11482323/

相关文章:

java - SWIG:从普通 C++ 到工作包装器

c++ - 如何让最小化和最大化按钮出现在 wxDialog 对象上

c++ - 将项目转换为支持 Unicode 后,CreateProcess 不运行 .cmd 文件

oop - 相互需要的对象

c++ - 如何解决不合格名称查找问题

c++ - Asterisk C++ API

linux - Linux 的面向对象 shell?

javascript - 新方法看不到 "this"(JavaScript)

c# - 表单设计器打破了通用抽象 UserControl

ruby-on-rails - Rails 模板 - 将索引添加到 :created_at using generate