继承两个多态类

时间:2010-01-28 23:58:17

标签: c++ multiple-inheritance virtual-functions

给出以下代码

class T {
    public:
        virtual ~T () {}
        virtual void foo () = 0;
};

class U {
    public:
        U() {}
        ~U() {}
        void bar () { std::cout << "bar" << std::endl; }
};

class A : public U, public T {
    public:
        void foo () { std::cout << "foo" << std::endl; }
};

int main () {
    A * a = new A;

    std::vector<U*> u;
    std::vector<T*> t;

    u.push_back(a);

    t.push_back(reinterpret_cast<T*>(u[0]));

    u[0]->bar ();
    t[0]->foo ();

    delete a;
    return 0;
}

我得到了我期望的输出

bar
foo

但是,如果我将U的定义更改为

class U {
    public:
        U() {}
        virtual ~U() {}
        virtual void bar () { std::cout << "bar" << std::endl; }
};

我仍然编译正常,没有警告/错误,但现在输出

bar
bar

虚拟声明是什么阻止我调用foo

3 个答案:

答案 0 :(得分:4)

首先,您的示例中没有虚拟基类。包含虚函数的类称为 polymorphic 。 (在C ++中有“虚拟基类”这样的东西,但它与你的例子无关。)

其次,代码的行为不依赖于任何虚拟声明。您已使用reinterpret_cast故意破坏了基指针的完整性。因此,代码的行为是 undefined

从一个基指针到另一个指针的直接转换(这是你在代码中尝试做的)被称为交叉投射。 C ++中唯一可以进行交叉投射的演员是dynamic_cast

t.push_back(dynamic_cast<T *>(u[0])); 

您可以在没有dynamic_cast的情况下执行间接交叉投射,但为此必须先使用A *向下转换指向派生类型的指针(static_cast),然后将其上转换为另一个基指针类型

t.push_back(static_cast<A *>(u[0])); // upconversion to `T *` is implicit

答案 1 :(得分:1)

如果您使用reinterpret_cast,您将失去所有保证,而您所做的任何事情都是“未定义的行为”。在这种情况下,我预计VMT会搞砸,或者VPTR会被覆盖。

作为一个例子,当我编译上面的第一个代码时,我在编译器上执行了段错误。

如果你真的想要“交叉执行”,你应该从一个公共基类派生,并通过U和T 虚拟: virtual public)继承该基类,或者使用{ {1}}代替dynamic_cast

答案 2 :(得分:0)

t一样填充u

t.push_back(a);

您不需要reinterpret_cast,因为AT