Reputation: 505
class Base {
public:
virtual void f(float) { cout << "Base::f(float)\n"; }
};
class Derived : public Base {
public:
virtual void f(int) { cout << "Derived::f(int)\n"; }
};
int main() {
Derived *d = new Derived();
Base *b = d;
b->f(3.14F);
d->f(3.14F);
}
-C++ does not support contravaraint return type, so the f(int) does not override f(float)
-Polymorphism is supported by C++, so both d and b should point to vtable for the derived class.
-vtable for derived class is something like 0: f(float), 1: f(int) etc.
My answer for the question is Base::f(float) is called twice, but the answer is:
Base::f(float) Derived::f(int)
Why is this the case? Does accessing derived class from different pointer enforce certain rules? Far as I am aware, object slicing only occurs when using copy-ctor or copy-assignment, with pointers, they should all point to the same vtable.
Upvotes: 3
Views: 241
Reputation: 19863
My take on this is that there is an implicit conversion of float to int when you call d->f(3.14F)
Your Derived
class actually has 2 entries for f()
void f(int);
void f(float);
This is confirmed with g++ with the -fdump-class-hierarchy flag. We can see the output as follow :
Vtable for Base
Base::_ZTV4Base: 3u entries
0 (int (*)(...))0
4 (int (*)(...))(& _ZTI4Base)
8 (int (*)(...))Base::f
Vtable for Derived
Derived::_ZTV7Derived: 4u entries
0 (int (*)(...))0
4 (int (*)(...))(& _ZTI7Derived)
8 (int (*)(...))Base::f
12 (int (*)(...))Derived::f
Your Derived
class does not touch the f function from the base class since the definitions do not match. The code compiles because there is a implicit conversion which exists between float and int.
Try the following
class Derived : public Base {
public:
virtual void f(std::string) { cout << "Derived::f(string)\n"; }
};
Then this code will not compile as Derived:f(...) will hide the Base::f(...) definition. This is often referred as inheritance shadowing.
So calling b->f(3.14F) will resolve within the Base table and d->f(3.14F) will resolve with the Derived table, which shadows Base.
Upvotes: 1
Reputation: 169018
Methods in different classes do not overload together; defining another f()
in Derived
prevents the one in Base
from being considered during overload resolution.
You need to explicitly bring base definitions into derived classes when you want to add new overloads without hiding the ones defined in base classes.
public:
using Base::f;
Upvotes: 4