If I have this structure:

class Parent
{
public:
 virtual void MyFunction() {// do something}
};


class Child
{
public:
 virtual void MyFunction() {// do something else}
};

The Parent::MyFunction() seems to always be called, even with:

Child MyChild;
MyChild.MyFunction();

Is this expected?

David

Recommended Answers

All 10 Replies

I wouldn't expect that...

If I run this:

#include <iostream>
using std::cout;
using std::endl;

class Parent
{
public:
 virtual void MyFunction() { cout << "Parent" << endl;}
};


class Child
{
public:
 virtual void MyFunction() { cout << "Child" << endl; }
};

int main() {
  Child myChild;
  myChild.MyFunction();
  std::cin.get();
  return 0;
}

I get "Child". I'm using MS VS2008.

Is there something else in the structure of your function(s) that may be redirecting to Parent::myFunction() during execution? Are you using some sort of cast? What compiler are you using?

Hm, no it looks exactly like the demo as far as I can tell. Strange - I fixed it by making it pure virtual and putting the "nothing" implementation in other subclasses (I don't have time to really look into it now). I just wanted to see if there was some rule about "if you define it inside the class declaration then virtual doesn't work" or something. I guess not.

It looks like you forgot to tell the Child class to inherit from the Parent.

Try

class Child : public Parent
{
   ...
};

In the class definitions, class Child is not derived from class Parent, at least in the example shown. IE: it should look like this:

class Parent
{
public:
 virtual void MyFunction() {// do something}
};
 
 
class Child : public class Parent
{
public:
 virtual void MyFunction() {// do something else}
};

Haha you're right - typo in the demo - no wonder it worked for you Fbody :) In the real situation the child is indeed derived from the parent.

It looks like you forgot to tell the Child class to inherit from the Parent.

Try

class Child : public Parent
{
   ...
};

I made the change just to see what happens. Same result. It output "Child" again.

There must be a cast or a redirect somewhere that you're missing.

Well, it should work. What compiler are you using?

In any case, I tried it with GNU C++ 4.4.4 and it works fine - I get "Child" for output.

gcc 4.4

Here is the real test to see if the virtual function is working properly:

#include <iostream>
using std::cout;
using std::endl;

class Parent
{
public:
 virtual void MyFunction() { cout << "Parent" << endl;}
};
 
 
class Child : public Parent
{
public:
 virtual void MyFunction() { cout << "Child" << endl;}
};

int main(void)
{
    Child myKid;
    Parent& mySelf = myKid;
    myKid.MyFunction();
    mySelf.MyFunction();
    return 0;
}

The expected output is:

Child
Child

There are indeed special rules about virtual functions, especially when they are inlined. But none would explain what you have observed. Basically, the special rules are about allowing the compiler to by-pass the dynamic binding (vtable lookup) in cases where the object type and thus the virtual function call is obvious.

First of all, if you have Child myChild; myChild.MyFunction(); , then this is never going to be a virtual call. In that case, the type of myChild is an object, not a reference or pointer, there is no reason for the compiler to delay the binding of the call to run-time, it will be bound at compile-time (i.e. the function will not be looked up in the vtable).

Second, there are cases where even if the call originates from a reference or pointer to an object, the compiler is also allowed to bypass the vtable if it is able to figure out what the type of the object is. For example:

Child myChild;
Parent& myParent = myChild;
myParent.MyFunction();

In this case it is quite likely that the compiler will understand that myParent actually refers to an object of type Child and will call its member function directly, bound at compile-time, bypassing the vtable. The more complex the situation is, the less chance there is for the compiler to be able to do this, it just depends on how clever the compiler is (and I guess the level of optimization performed). For instance, with GCC 4.6, the above will by-pass dynamic binding when optimization is turned on (-O1-2-3), but will do a vtable look-up if optimization is off. It's quite easy to see these things when printing the assembly listings, a normal member function call will look like:

call    _ZN5Child10MyFunctionEv    //normal function call.

While a vtable lookup will look like this:

movq    $_ZTV5Child+16, (%rsp)  //vtable look-up
        movq    (%rsp), %rax
        movq    %rsp, %rdi
        call    *(%rax)       //virtual function call.

Finally, if any of the cases above apply, then the virtual function is now called just like any non-virtual member function, so the compiler has an opportunity to inline the call if it deems it advantageous.

Still, I think that your example is really weird. It should not behave like this. There is pretty much a golden rule for C++ compiler, which is that polymorphism should always work as expected. It should never produce code that breaks like that.

Note: In many applications, for binary compatibility reasons and other reasons, the use of inline virtual functions is highly discouraged or even forbidden. It's kinda hard to explain why here, but it's just something to be aware of.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.