C++是否允许多级虚拟化?

Lew*_*wis 8 c++ oop polymorphism virtual inheritance

我有一个名为Object的基类.PhysicsObject继承自Object.Ball继承自PhysicsObject,而SoftBall继承自Ball.像这样的东西:

Object
 |
PhysicsObject
 |
Ball
 |
SoftBall
Run Code Online (Sandbox Code Playgroud)

我有一个名为foo()的方法,它在Object中声明为虚拟(给定一个实现,因此不是纯虚拟),然后在PhysicsObject和Ball中再次声明和实现为虚拟.最后,SoftBall再次实现foo()而不将其声明为虚拟.

如果我有一个指向SoftBall的Object*,那么将调用SoftBall的foo()版本吗?如果没有,有没有办法达到这个效果?基本上,多态的这个方面是否仍然可以在多个继承级别上工作?

bdo*_*lan 9

如果在基类中声明虚函数,并在派生类中声明具有相同签名的函数,则它将自动变为虚拟(即使中间有任意数量的类层).所以问题的答案是,是的,foo()将调用SoftBall实现.

但请注意,如果签名有任何差异,则隐藏虚拟功能.例如:

class Object {
public:
  virtual void foo();
};

class InBetween : public Object {
  // assume it has no foo()s
};

class A : public InBetween {
public:
  void foo() const; // DOES NOT OVERRIDE; ((Object *)pA)->foo() calls Object::foo()
                    // However pA->foo() calls this
};

class B: public InBetween {
public:
  void foo() const; // Does not override; pB->foo() calls this if pB is const
  void foo(); // Does override; ((Object *)pB)->foo() calls this. pB->foo() also calls this if pB is non-const
};
Run Code Online (Sandbox Code Playgroud)


seh*_*ehe 6

如果我有一个指向SoftBall的Object*,那么将调用SoftBall的foo()版本吗?如果没有,有没有办法达到这个效果?基本上,多态的这个方面是否仍然可以在多个继承级别上工作?

如果相应的重载在基类中是虚拟的,C++将方法定义为虚拟(与其他OO语言不同,其中必须明确标记重写).

http://codepad.org/pL09QWNN


请注意,使用更多成分,您可以获得非常时髦:

#include <iostream>

struct A { virtual void foo() { std::cout << "A::foo();" << std::endl; } };
struct B { virtual void foo() { std::cout << "B::foo();" << std::endl; } };

struct Oa: A, B { using A::foo; };
struct Ob: A, B { using B::foo; };

#define TEST(a) std::cout << #a << ":\t"; a

int main()
{
    A a;
    B b;
    Oa oa;
    Ob ob;

    TEST(a.foo());
    TEST(b.foo());
    TEST(oa.foo());
    TEST(ob.foo());

    std::cout << "But oa through different references:" << std::endl;
    {
        A& ar = oa;
        TEST(ar.foo());

        B& br = oa;
        TEST(br.foo());
    }

    std::cout << "And ob through different references:" << std::endl;
    {
        A& ar = ob;
        TEST(ar.foo());

        B& br = ob;
        TEST(br.foo());
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

尝试预测这里打印的内容.混合后,它会变得更有趣:

  • (mutable/const/volatile qualified)重载
  • (冲突的)默认参数

我记得以琐事问题的形式阅读了很多可怕的例子,我希望在面试中永远不会遇到.虽然我知道我会回答:"如果你有这样的代码,我不确定我是否想要这份工作"?

你可以去看看Herb Sutter,Scott Meyer,你会惊奇地发现我们的文明 - 很好的小语言 - 喜欢被称为C++的陷阱是什么