C ++ polymorphism, name resolution for derived class

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 f (int) does not override f (float)

-Polymorphism is supported by C ++, so both d and b must point to the vtable for the derived class.

-vtable for a derived class is something like 0: f (float), 1: f (int), etc.

My answer to Base :: f (float) is called twice, but the answer is:

Base :: f (float) Derived :: f (int)

Why is this so? Does a derived class access certain rules from different pointers? As far as I know, slicing of objects only happens when using copy-ctor or copy assignment with pointers, they all have to point to the same vtable.

+3


source to share


2 answers


Methods in different classes are not overloaded together; defining another f()

in Derived

prevents the issue from being considered Base

during congestion resolution.

You need to explicitly inject base definitions into derived classes if you want to add new overloads without hiding those defined in base classes.



public:
    using Base::f;

      

+3


source


I believe there is an implicit float to int conversion when called d->f(3.14F)

Your class Derived

has 2 entries for f ()

void f(int);
void f(float);

      

This is confirmed by g ++ with the -fdump-class-hierarchy flag. We can see the result as follows:

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 class Derived

does not touch the function f from the base class, as the definitions do not match. The code compiles because there is an implicit conversion that exists between float and int.

Try to run

class Derived : public Base {
public:
virtual void f(std::string) { cout << "Derived::f(string)\n"; }
};

      

Then this code won't compile like Derived: f (...) will hide Base :: f (...) definition. This is often referred to as inheritance shading.

So the call to b-> f (3.14F) will resolve in the base table, and d-> f (3.14F) will resolve with the Derived table, which is the base shadow.

+1


source







All Articles