Does C ++ provide multiple levels of virtuality?

I have a base class Object. PhysicsObject inherits an object. Ball inherits from PhysicalObject, and SoftBall inherits from Ball. Something like that:

Object | PhysicsObject | Ball | SoftBall 

I have a foo () method declared virtual in Object (subject to implementation, not pure virtual), and then declared and implemented as virtual again in PhysicsObject and Ball. Finally, SoftBall implements foo () again without declaring it virtual.

If I have an object * pointing to SoftBall, will the foo () version of SoftBall be called? If not, is there a way to achieve this effect? Basically, does this aspect of polymorphism still work on more than one level of inheritance?

+7
source share
3 answers

If I have an object * pointing to SoftBall, will the foo () version of SoftBall be called? If not, is there a way to achieve this effect? Basically, does this aspect of polymorphism still work on more than one level of inheritance?

Yes

C ++ defines methods as virtual if the corresponding overload is virtual in the base class (unlike other OO languages, where overrides must be explicitly marked).

http://codepad.org/pL09QWNN


Please note that with some additional ingredients you can get really scared:

 #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; } 

Try to predict what is printed here. This gets a lot more interesting when you mix:

  • (mutable / const / volatile qualified) overloads
  • (conflicting) default arguments

I remember that I read quite a few more and less terrifying examples in the form of a trifling question, which I hope never to meet in an interview. Although I know what I would answer: "If you have this code, I'm not sure I want a job" ?.

You can take a look at Herb Sutter, Scott Meyer, and you will be amazed that the traps are hidden in our otherwise-civilized-good-less-lingual-loving-somehow in C ++

+6
source

If you declare a virtual function in the base class and declare a function with the same signature in the derived class, it will be automatically made virtual (even with any number of layers between classes). So, the answer to your question is: yes, the SoftBall foo() implementation will be called.

Beware, however, that if there is any difference in signature, then the virtual function will be hidden. For example:

 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 }; 
+8
source

If I have an object * pointing to SoftBall, can SoftBall's name the version of foo ()? If not, is there a way to achieve this effect? Basically, does this aspect of polymorphism still work on more than one level of inheritance?

Yes.

Of course, you could just try it ...;)


For posterity, here is my test file (which assumes cout in scope):

 struct Object { virtual void foo() {} }; struct PhysicsObject : Object {}; struct Ball : PhysicsObject {}; struct SoftBall : Ball { virtual void foo() { cout << "SoftBall"; } }; int main() { SoftBall sb; Object* o = &sb; o->foo(); } // Output: "SoftBall" 
+1
source

All Articles