Reputation: 709
for which reason this program:
#include <iostream>
using namespace std;
class Base {
public:
Base() { cout << "Costruttore Base" << endl; }
virtual void foo(int) { cout << "Base::foo(int)" << endl; }
virtual void bar(int) { cout << "Base::bar(int)" << endl; }
virtual void bar(double) { cout << "Base::bar(double)" << endl; }
virtual ~Base() { cout << "Distruttore Base" << endl; }
};
class Derived : public Base {
public:
Derived() { cout << "Costruttore Derived" << endl; }
void foo(int) { cout << "Derived::foo(int)" << endl; }
void bar(int) const { cout << "Derived::bar(int)" << endl; }
void bar(double) const { cout << "Derived::bar(double) const" << endl; }
~Derived() { cout << "Distruttore Derived" << endl; }
};
int main() {
Derived derived;
Base base;
Base& base_ref = base;
Base* base_ptr = &derived;
Derived* derived_ptr = &derived;
cout << "=== 1 ===" << endl;
base_ptr->foo(12.0);
base_ref.foo(7);
base_ptr->bar(1.0);
derived_ptr->bar(1.0);
derived.bar(2);
return 0;
}
In the call base_ptr->bar(1.0);
is called Base::bar(double)
, instead in the derived_ptr->bar(1.0);
is called Derived::bar(double) const
.
I understood that is about the const
keyword, but I don't understand why the compiler is choosing different overloaded functions.
If I remove the const
keyword, everything is working as expected, calling in both cases the Derived::bar
Upvotes: 4
Views: 365
Reputation: 21576
C++11 added the override
specifier to prevent these kind of surprises. Use, the override
keyword, and the compiler will only compile your code, if it does override.
Taking the supposedly override of bar(int)
(this also applies to the bar(double)
:
class Base {
public:
....
virtual void bar(int) { cout << "Base::bar(int)" << endl; }
};
class Derived : public Base {
public:
...
//This isn't an override, program is well formed
void bar(int) const { cout << "Derived::bar(int)" << endl; }
};
The bar
member function in Derived
did not override the base class' own. Because the const
qualifications are different, hence the member function signatures are different. All you did in the derived class was to add a new overload and hide that of the base class'.
Add the override
keyword in the derived class' and the compiler will give a diagnostic if it doesn't override.
class Base {
public:
....
virtual void bar(int) { cout << "Base::bar(int)" << endl; }
};
class Derived : public Base {
public:
...
//This isn't an override, program is ill-formed, diagnostic required
void bar(int) const override { cout << "Derived::bar(int)" << endl; }
};
To override, the member function signatures must be the same.
class Base {
public:
....
virtual void bar(int) { cout << "Base::bar(int)" << endl; }
};
class Derived : public Base {
public:
...
//This overrides
void bar(int) override { cout << "Derived::bar(int)" << endl; }
};
So, learn to use the override keyword whenever you want to override, it will save you some headaches.
Upvotes: 2
Reputation: 710
It's because you're not really overriding the function bar(). You are defining a new function bar() in the derived class with a different signature.
So either remove the const in the derived class or add a const to the signature of bar() in the upper class. (Or keep it as it is but know that you now have two functions named bar() in derived class, one of which is hidden)
Upvotes: 2
Reputation: 27577
That's because const
changes the signature of the function, so they're different. Either make both the base class and derived class const
or not, otherwise one won't override the other.
Upvotes: 3