我希望如果 foo 在类 D 中声明,但没有标记为virtual,那么下面的代码将调用 foo 在 D 中(无论 d 的动态类型)。

D& d = ...;
d.foo();

但是,在以下程序中,情况并非如此。有谁能解释一下?如果方法覆盖虚函数,它是否会自动虚拟?

#include <iostream>

using namespace std;

class C {
public:
        virtual void foo() { cout << "C" << endl; }
};

class D : public C {
public:
        void foo() { cout << "D" << endl; }
};

class E : public D {
public:
        void foo() { cout << "E" << endl; }
};

int main(int argc, char **argv)
{
        E& e = *new E;
        D& d = *static_cast<D*>(&e);
        d.foo();
        return 0;
}

上述程序的输出是:

E
有帮助吗?

解决方案

标准10.3.2(class.virtual)说:

  

如果虚拟成员函数vf在类Base和Derived中直接或间接派生的类中声明,则声明具有与Base :: vf相同名称和相同参数列表的成员函数vf,然后派生:: vf也是虚拟的(无论是否如此声明)并且它会覆盖*

     

[脚注:具有相同名称但作为虚函数的不同参数列表(子句)的函数不一定是虚拟的,也不会覆盖。在覆盖函数的声明中使用虚拟说明符是合法的但是冗余的(具有空语义)。在确定覆盖时不考虑访问控制(子句class.access)。 ---结束foonote]

其他提示

快速回答可能不是,但正确答案是

C ++不知道函数隐藏,所以覆盖虚函数而没有虚拟关键字标记也能实现虚函数。

您没有创建e的对象的任何副本并将其放入d中。所以d.foo()遵循正常的多态行为并调用派生类方法。在基类中声明为virtual的方法也会在派生类中自动变为虚拟。

输出(“E”)的行为完全符合预期的行为。

原因: 该引用的动态(即运行时)类型为E.您正在对D进行静态向上转换,但这并不会改变对象的实际类型。

这就是虚拟方法和动态调度背后的想法:在这种情况下,您可以看到实例化类型的行为,即E。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top