consider the following program:
class Base {
public:
virtual void foo() const {
cout << "Base::foo()" << endl;
}
};
class Derived : public Base {
public:
virtual void foo() {
cout << "Derived::foo()" << endl;
}
};
void func(Base& obj) {
obj.foo();
}
void main() {
Derived d;
func(d); // Base::foo() is printed
}
If I remove the const
from the Base
class foo
method then Derived::foo()
is called.
I can't seem to understand this behavior.
1) What is the reason for this behavior?
2) Is this decided at compile time or runtime?
Thanks
An override method is a new implementation of a member that is inherited from a base class. The overridden base method must be virtual, abstract, or override. Here the base class is inherited in the derived class and the method gfg() which has the same signature in both the classes, is overridden.
Function Overriding in C++ It redefines a function of the base class inside the derived class, which overrides the base class function. Function overriding is an implementation of the run-time polymorphism. So, it overrides the function at the run-time of the program.
The main advantage of method overriding is that the class can give its own specific implementation to a inherited method without even modifying the parent class code.
Calling Parent class's overridden method from Child class's method using super keyword. from Derived class function will call base class version of display() function i.e.
You aren't overriding the method, since Derived::foo
isn't exactly the same.
To override a method, the base and overridden versions must be identical, including const
-ness.
In the derived class, the function signature is this:
virtual void foo(); //Derived::foo
which doesn't mention const
. Its a non-const member function, while the Base::foo
is a const member function. They're two different functions, because const
is a part of the function signature.
virtual void foo() const; //Base::foo
Derived class does NOT override this function, instead it adds another function.
So the fix is this:
class Derived : public Base {
public:
virtual void foo() const {
cout << "Derived::foo()" << endl;
}
};
As const
is a part of the function signature. So you must mention it when you intend to override base's foo.
@davka's asked:
so why the const version is selected over the non-const? Is there any rule or it just happened to be the first option?
Its because the static type of obj
is Base
, and function name is resolved based on the static type of object. Base
doesn't even have non-const version. So there is no question of it being selected or rejected. It doesn't exist in Base
to begin with.
void func(Base& obj) {
obj.foo(); //calls Base::foo
}
However, if you change the above code to the following:
void func(Derived & obj) {
obj.foo(); //calls Derived:foo
}
Now non-const version will be selected, because Base::foo
is hidden in Derived
class.
Since Derived::foo
hides the Base::foo
, so you cannot call the latter using an instance of Derived
.
Now, lets unhide Base::foo
and do some more experiments.
class Derived : public Base {
public:
using Base::foo; //<----------------this unhides Base::foo
virtual void foo() {
cout << "Derived::foo()" << endl;
}
};
Now in Derived, both functions (const as well as non-const version) are available, unhidden. Now few interesting questions.
Since now Derived has both functions unhidden, which function will be called in each function below?
void f(Derived& obj) {
obj.foo(); //Which function? Base::foo or Derived::foo?
}
void g(const Derived & obj) {
obj.foo(); //Which function? Base::foo or Derived::foo?
}
First one will call Derived::foo
which is non-const version, and second one will call Base::foo
which is const version. The reason is simple, with const object, only const functions can be invoked, but with non-const objects, both can be invoked, however non-const version is selected if its available.
See online demo : http://www.ideone.com/955aY
In C++, you can have two functions with the same name and the same parameters, where the only difference that one is const
and one is not.
The idea is that you sometimes want different behaviors. For example, an access function function might have different return types:
class MyClass
{
public:
virtual Xxx * GetXxx();
virtual Xxx const * GetXxx() const;
// ....
}
You can override these functions individually.
In your case, as you call foo
from a non-const object, you called the non-const variant of the function. As you had overridden the const-variant, the one in the base class is the one being called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With