wilson100
wilson100

Reputation: 359

C++ virtual function in type casting of reference

I have a question in virtual function and reference. It's from a puzzle when I try to prepare interview. I google it for a while but cannot see the exact case.

The code is given as:

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

class B: public A{
public:
 void foo() {cout << "B::foo" << endl;}
};

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

int main(void){
 C c;

 B *q;
 q = &c; q->foo();
 return 0;
}

My thought to the output will be B::foo, but the answer is actually C::foo. Can someone tell me why the vtable wont choose B's implementation? Thanks

Upvotes: 0

Views: 1373

Answers (6)

CB Bailey
CB Bailey

Reputation: 792059

foo is virtual in B because it overrides a virtual function from a base class even though it is not explicitly declared as virtual.

The most derived type of the object called through q->foo() is C and C's final overrider for foo with the signature void foo() is C::foo so this is the function that is called.

Upvotes: 2

Adam Zalcman
Adam Zalcman

Reputation: 27233

foo() is a virtual function, which means that the version defined in the class whose instance is actually pointed to by q is called rather than the one defined in the class in the pointer's type.

Remember that a member function is virtual once it is marked virtual somewhere up the class hierarchy, i.e. one needs not explicitly mark the function as virtual again in classes B and C since this has already been done in class A.

Upvotes: 0

Jerry Coffin
Jerry Coffin

Reputation: 490178

If foo was not virtual, then the function called would be based on the type of the pointer, and B::foo() would be called.

Since foo is defined virtual in the base class, it remains virtual in all derived classes. That being the case, the function that's called is based on the type of object pointed at rather than the type of the pointer. Since the object pointed at is a C, the function that gets called is C::foo().

Upvotes: 2

Praetorian
Praetorian

Reputation: 109159

Can someone tell me why the vtable wont choose B's implementation?

That is the whole point of having virtual functions, so that calling an overriden method through a base class pointer will still call the method from the derived class.

q is of type B *, but it is pointing to a C object. So, when you call the virtual function foo() the C::foo() implementation gets called.

Even though foo() is not marked virtual in B and C, it is still a virtual function because it is declared as such in A.

If you want B::foo() to get called you'll need to call it explicitly.

q->B::foo();

Upvotes: 0

Tio Pepe
Tio Pepe

Reputation: 3089

Because q points to a C object and its virtual function table contains a virtual function foo. Remember that any virtual function declared in a class is virtual in any derived class. This is the way of using base classes to access to derived ones.

Upvotes: 1

Atmocreations
Atmocreations

Reputation: 10061

Afaik:

Once vtables are used - which is in this case forced by the virtual declaration of A::foo - it's not important what type you declare, it'll always call the method of most specific method - which is in this case C::foo.

Upvotes: 0

Related Questions