Consider this code:
#include <iostream>
class Base
{
public:
void Message()
{
std::cout<<"You are calling the function of class Base ";
}
};
class Derived : public Base
{
public:
void Message()
{
std::cout<<"You are calling the function of class Derived ";
}
};
int main()
{
Derived obj1;
obj1.Base::Message();
return 0;
}
These two lines of code:
Derived obj1;
obj1.Base::Message();
Call the class Derived which is derived from Base. The second line of code calls the Base class overridden function Message.
Why does the standard introduce obj1.Base::Message() when we can directly call the function Message with this code?
Base obj1;
obj1.Message();
Base::Message is necessary if you want to call that function on an object of type Derived. In the particular example you give, it's true that an alternate way of doing this is to use static_cast<Base&>(derived).Message(). However, in the case that Message is a virtual function, this won't work--you would always get Message from the most derived class.
One place where this is often used is if you are overriding a virtual function, but want to call the base function from within the derived one. For example:
class Base
{
public:
virtual void Message()
{
std::cout<<"You are calling the function of class Base ";
}
};
class Derived : public Base
{
public:
void Message() override
{
Base::Message();
std::cout<<"(and now for the Derived-only part of the message)";
}
};
Related
Consider:
#include <iostream>
class Base
{
public:
virtual void foo() { std::cout << "Base::foo()\n"; };
};
class Derived : public Base
{
public:
void foo() override
{
std::cout << "Derived::foo()\n";
Base::foo();
}
};
int main()
{
Derived obj;
obj.foo();
return 0;
}
This is my code. Why can I call Base::foo() in the Derived class if I already redefined it in Derived class. Why doesn't the compiler delete Base::foo in class Derived after redefine?
"why compiler doesn't delete Base::foo in class Derived after redefine"
Because that isn't what virtual and override do. When you provide an override to a base class function, you do not replace it. You are defining a new version for that function. The base class's implementation continues to exist and to be accessible.
Consider the following code. Someone can still use a Base object, and the behaviour should not be changed because Derived exists. The output for base_obj.foo() should continue to be "Base::foo()" regardless of the existance of Derived. :
#include <iostream>
class Base
{
public:
virtual void foo() { std::cout << "Base::foo()\n"; }
};
class Derived : public Base
{
public:
void foo() override { std::cout << "Derived::foo()\n"; }
};
int main()
{
Derived obj;
obj.foo();
Base base_obj;
base_obj.foo();
return 0;
}
Also consider that multiple classes can derive from Base. I could add a class MyClass : public Base with its own version of foo(), and it should not interfere with how Base or Derived objects behave.
If overriding a member function would cause the base member function to be entirely replaced or removed, it becomes nearly impossible to reason about code without reading carefully every class that derives from it. And unless your IDE provides tools for that, it implies reading all of the code base. It would make it C++ code that uses polymorphism extremely difficult to understand.
A very similar question was asked here:
C++: Overriding a protected method which is called by another method
However, I would like to know how to override a callback function in a Base class so that another method can call the derived class's callback from the constructor rather than the Base class's callback.
I've given an example below:
#include <iostream>
class Base {
protected:
virtual void callback() {
std::cout << "Base" << std::endl;
}
public:
Base() {
callback();
}
};
class Derived : Base {
protected:
void callback() override {
std::cout << "Derived" << std::endl;
}
public:
// Use Base's constructor to call print
Derived() : Base() { }
};
int main() {
Base B;
Derived D;
return 0;
}
The output is:
Base
Base
but I would like the output to be:
Base
Derived
This cannot be done. You can see the explanation in this post.
The object is constructed from base - up. The base class gets constructed first and then the members of the derived class extend / override the base class. So when the base constructor is running, the members of the derived class don't exist yet, so you cannot call them.
Not sure what you need this for, but you can just call the same method again from the derived class and you should see the output of both calls (from base and from derived).
How do I make a base class virtual function so that it always is called when a derived class calls its version of the function? I know I can call the base classes function by writing something like BaseClass::foo() at the beginning of the the function DerivedClass::foo(), but what if I want it to be called by default, without the creator of the derived class even knowing that the base classes function does anything?
class BaseClass
{
BaseClass();
virtual void foo() {
printf("base");
}
}
class DerivedClass : public BaseClass
{
DerivedClass();
void foo() {
printf("derived");
}
}
int main()
{
DerivedClass dc;
dc.foo();
}
Should print:
base
derived
That's not directly possible. You could split the function in non-virtual foo on the base class and (pure) virtual fooCore on the derived classes:
class Base {
protected:
virtual void fooCore() = 0;
public:
void foo(){
// do stuff, then call method of derived class
this->fooCore();
}
};
class Derived {
protected:
void fooCore() override {
//actual
};
};
From the "outside" the call Base::foo() stays the same.
When i run this code , Output is as expected "This is derived 2" due to late binding because we used virtual function at the base class.
#include <iostream>
using namespace std;
class Base {
public :
virtual void show() {
cout<<"This is base class"<<endl;
}
};
class Derived : public Base {
public:
void show() {
cout<<"This is derived class"<<endl;
}
};
class D2 : public Derived {
public :
void show () {
cout<<"This is derived 2"<<endl;
}
};
int main() {
Base *obj = new D2();
obj->show();
return 0;
}
Similarly, if i change the code to
#include <iostream>
using namespace std;
class Base {
public :
void show() {
cout<<"This is base class"<<endl;
}
};
class Derived : public Base {
public:
virtual void show() {
cout<<"This is derived class"<<endl;
}
};
class D2 : public Derived {
public :
void show () {
cout<<"This is derived 2"<<endl;
}
};
int main() {
// your code goes here
Derived *obj = new D2();
obj->show();
return 0;
}
Same thing happens, virtual function is defined in the base class which in this case is "Derived" class and Pointer is also of the type "Derived" so again calling show() gives me the most derived version.
But i can't understand what is happening when virtual function is defined in the "Derived" class and i use the base pointer of the class "Base". The output of the following code
#include <iostream>
using namespace std;
class Base {
public :
void show() {
cout<<"This is base class"<<endl;
}
};
class Derived : public Base {
public:
virtual void show() {
cout<<"This is derived class"<<endl;
}
};
class D2 : public Derived {
public :
void show () {
cout<<"This is derived 2"<<endl;
}
};
int main() {
// your code goes here
Base *obj = new D2();
obj->show();
return 0;
}
Output : "This is base class". Please help me understand this output.
The reason your last snippet does not work is that the void show() function is virtual in your derived class only, but not in the base class. If any of the classes derived from Derived would override it, and then you call it through a pointer to Derived, you would see polymorphic behavior. The way you did it, however, the call through the base pointer is non-virtual, hence it is dispatched to the Base's implementation.
You can fix this by declaring show virtual in the base class:
class Base {
public :
virtual void show() {
// ^^^^^^^
cout<<"This is base class"<<endl;
}
};
Demo 1
or by accessing D2 through a pointer to Derived:
Derived *obj = new D2();
obj->show();
Demo 2
In your final example, D2 is a Base*, so whether or not that class gets derived doesn't matter.
If you had made obj a pointer to Derived or D2, the results would be different.
The static type of object obj is Base *
Base *obj = new D2();
So the compiler can call only member functions declared in this class. In class Base function show is not virtual. So it was selected by the compiler at compilation time. Base class knows nothing about virtual functions declared in derived classses. In your example the base class even does not have a table of addresses of virtual functions because neither function in the class declared as virtual.
That a virtual function of a derived class would be called the derived class shall to substitute the address of the base class virtual function for the address of its own function in the table of addresses of virtual functions in the base class.
So heres my code:
#include <iostream>
class cBase
{
public:
void vf(int)
{
std::cout << "cBase\n";
}
};
class cDerived : public cBase
{
public:
void vf(int)
{
std::cout << "cDerived\n";
}
};
int main()
{
cBase b;
cDerived d;
b.vf(0);
d.vf(0);
}
This example hides the function vf() of the base class and calls the vf() function of the derived class. Heres another piece of code:
#include <iostream>
class cBase
{
public:
virtual void vf(int)
{
std::cout << "cBase\n";
}
};
class cDerived : public cBase
{
public:
void vf(int)
{
std::cout << "cDerived\n";
}
};
int main()
{
cBase b;
cDerived d;
b.vf(0);
d.vf(0);
}
Now, the vf() function of the derived class overrides the vf() function of the vase class.
So my question is: what is the point of virtual functions if i can achieve the same result with the default hiding mechanism of c++? Am i missing something here? Thanks in advance!
To make polymorphism work you need to work on pointers or references. When you use dot operator on object that is neither pointer or reference then virtual table is not used to call proper virtual function.
To see how it works, create derived object dynamically, assign it to base class pointer and call your function on it. This will call implementation from your derived class.
virtual functions give run time polymorphism. Your objects will not exhibit run time polymorphism which is when the same code using the same compile-time types can exhibit different behaviour based on the run time types of the objects in question. E.g:
void f(CBase& x) {
x.vf(0);
}
Without vf being virtual in CBase, the CBase::vf will be called even if the run time type of x is CDerived.