I have a base class called Object. PhysicsObject inherits from Object. Ball inherits from PhysicsObject, and SoftBall inherits from Ball. Something like this:
Object
|
PhysicsObject
|
Ball
|
SoftBall
I have a method called foo() that is declared virtual in Object (given an implementation, so not pure virtual), then declared and implemented as virtual again in PhysicsObject and Ball. Finally, SoftBall implements foo() again without declaring it as virtual.
If I have an Object* that points to a SoftBall, will SoftBall's version of foo() be called? If not, is there any way to achieve this effect? Basically, does this aspect of polymorphism still work over more than one level of inheritance?
In C++, once a member function is declared as a virtual function in a base class, it becomes virtual in every class derived from that base class. In other words, it is not necessary to use the keyword virtual in the derived class while declaring redefined versions of the virtual base class function.
A virtual function in C++ helps ensure you call the correct function via a reference or pointer. The C++ programming language allows you only to use a single pointer to refer to all the derived class objects.
Functions in derived classes override virtual functions in base classes only if their type is the same. A function in a derived class cannot differ from a virtual function in a base class in its return type only; the argument list must differ as well.
A C++ virtual function is a member function in the base class that you redefine in a derived class. It is declared using the virtual keyword. It is used to tell the compiler to perform dynamic linkage or late binding on the function.
If you declare a virtual function in a base class, and declare a function with the same signature in a derived class, it will automatically be made virtual (even with any number of layers of classes in between). So the answer to your question is, yes, the SoftBall implementation of foo()
will be called.
Beware, however, that if there is any difference in the signature, then the virtual function will be hidden instead. 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
};
If I have an Object* that points to a SoftBall, will SoftBall's version of foo() be called? If not, is there any way to achieve this effect? Basically, does this aspect of polymorphism still work over 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 have to be marked explicitely).
http://codepad.org/pL09QWNN
Note that with some more ingredients you can get really funky:
#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 gets printed here. It get's a lot more fun once you mixin:
I remember reading quite a lot of more and less horrendous examples in the form of trivia question I hope to never encounter in an interview. Although I know what I'd answer: "If you have code like this, I'm not sure I want the job"?.
You could go looking on Herb Sutter, Scott Meyer, and you'll be amazed what pitfalls lurk in our otherwise-so-civilized-nice-little-language-fondly-referred-to-as C++
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With