C ++将派生类存储在单个向量中,派生类不包含redifined方法

时间:2015-05-28 17:44:32

标签: c++ inheritance vector derived-class base-class

我有一个具有相当复杂的继承结构的程序,所以我不会用它来显示我的问题但是下面的结构使用了糟糕的样式来保持简单:

class A {
public:
    int va1;
    int va2;
    string va3;

    virtual void fa1(int x1, string x2) {
        // method body
    }

    int fa2 (bool y1, double y2) {
        // method body
    }

    A() {

    }

    virtual ~A() {

    }
};

class B :
    public A
{
public:
    bool ab1;
    double ab2;
    long double ab3;

    bool fb1(double x1) {
        //method body
    }

    long double fb2() {
        //method body
    }

    B(int z1) {
        ab2 = z1;
    }

    virtual ~B() {

    }
};

class C :
    public A
{
public:
    int ac1;

    long double fc1() {
              //method body
    }

    virtual void fa1(int x1, string x2) {
        // method body
    }

    C() {

    }

    virtual ~C() {

    }
};

如您所见,B和C主要由全新的变量和方法组成,而不是A中重新定义的变量和方法。 因此,使用A指针结合虚拟方法不会起作用。

到目前为止,我总是使用单独的向量或数组来派生类,因为我很少编写程序,这些程序主要由派生类组成,这些派生类只重新定义了基类'方法

我知道我不能简单地创建一个As矢量并输入B和C而不会丢失信息。

我的问题是,是否可以以指针或其他形式将As,B和C存储在单个向量中,并仍可访问A中不存在的所有方法和变量?

如果它不适用于向量,是否有替代方案(数组可能)?

代码可以包含现代C ++(标准,std :: string而不是char *等),因为不需要与C或传统C ++兼容。

1 个答案:

答案 0 :(得分:1)

这可以使用指针矢量或更好的矢量, shared_ptr 的矢量来完成:

vector<shared_ptr<A>> v;        // vector of shared ponters to A
v.push_back(make_shared<A>());
v.push_back(make_shared<B>(2));
v.push_back(make_shared<C>());

shared_ptr<A> pa = v[1];       // this one is a B but in real life we would'nt know
                               // I can use all the A methods without question
shared_ptr<B> pb = dynamic_pointer_cast<B>(pa);   // attempt to cast it to a B
if (pb) {                     // if casting succeded
    pb->fb2();                       // I call the B method 
} else cout << "Not a B"<<endl; // if not, I know that it's an A but not a B

原则是你存储在A的向量(共享)指针中。所以你可以一直访问它的A::成员。

由于您的基类是多态的(即它至少有一个虚函数),dynamic_cast dynamic_pointer_cast shared_ptr)可用于尝试将指针强制转换为派生类的指针(例如B)。如果转换成功(非空指针),则您知道可以访问B::成员。

使用shared_ptr与原始指针有助于内存管理:如果不再使用某个对象,则会自动删除它。

这是 online demo