Question about polymorphism & overloading - c++

#include <iostream>
class X{
public:
virtual void f() {std::cout << "1";}
};
class Y : public X{
public:
void f() {std::cout << "2";}
void g() {std::cout << "3";}
};
class Z : public Y{
public:
virtual void f() {std::cout << "4";}
void g() {std::cout << "5";}
virtual void k() {std::cout << "6";}
};
void main()
{
X *x = new Z;
Y *y = new Z;
Z *z = new Z;
x->f(); // 4
y->f(); // 4
y->g(); // 3
z->f(); // 4
z->g(); // 5
z->k(); // 6
system("PAUSE");
}
Output: 443456.
I got confused, why did it not print '2' when doing 'y->f()'? f() inside Y class isn't a virtual function.
I'd like to know more about it, thank you for the help.

why did it not print '2' when doing 'y->f(x)'? f() inside Y class isn't a virtual function.
Y::f is a virtual function. If a base class has a virtual function by the same name, then the derived class function is implicitly virtual as well.

First of all, overloading isn't relevant here--you don't have any overloaded functions (which would be functions with the same name, but different signatures, at the same scope).
Second, you're not really dealing much with virtual functions either. One one hand, it's true that you've (quite correctly) declared f() as a virtual function in your base class (X).
You've also overridden that virtual function in your derived class Y.
But, the primary time a virtual function means something is when you invoke the virtual function in an object of a derived class via a pointer (or reference) to the base class:
#include <iostream>
class base {
public:
virtual void f() { std::cout << "base::f()\n"; }
void g() { std::cout << "base::g()\n"; }
};
class derived : public base {
public:
virtual void f() { std::cout << "derived::f()\n"; }
virtual void g() { std::cout << "derived::g()\n"; }
};
int main() {
base *b = new base; // first case: pointer to base, base object
base *d = new derived; // second case: pointer to base, derived object
derived *d2 = new derived; // third case: pointer to derived, derived object
b->f(); // invokes base::f
b->g(); // invokes base::g
d->f(); // invokes derived::f
d->g(); // invokes base::g
d2->f(); // invokes derived::f
d2->g(); // invokes derived::g
}
So, in the first case, we have a base pointer, referring to a base object. With this, the derived class might as well not exist--we always get the base class member functions, regardless of whether they're virtual.
The case you asked about is pretty much the same as the third case in this code: we have a pointer to the derived object referring to an object of the derived class. Here again, it doesn't matter whether a function is virtual or not. Since we're using a pointer to a derived, we always get the derived version of each function, regardless of whether it's virtual or not.
The case where virtual functions get interesting is the second one, where we have a pointer to the base class, but it's referring to an object of the derived class. In this case, g() (which isn't virtual) is statically bound, so the function that gets called depends on the type of the pointer. Since we're using a pointer to base, we get base::g() even though the pointer is actually referring to a derived object.
But, with f() (which is virtual), we get "late binding"--even though we're using a pointer to base, when we invoke f(), we invoke derived::f(), because the object being pointed at is a derived object.
So yes, in your code, derived::f() is virtual because it's declared virtual in base--but even if it wasn't virtual, since you used a pointer to the derived class, you'd still have gotten derived::f() even if f() wasn't virtual at all.

Related

Force derived class to call base class function. How do I force the base class function to use virtual base class version of functions?

Suppose I have the following code
class A{
public:
void f1()
{
/*
* Other functions that happen here.
* These calls needs to be made at A's f1() function
* And cannot be in derived class.
*/
f2();
}
virtual void f2()
{
std::cout << "I am base class" << std::endl;
}
};
class B : A
{
public:
void f2()
{
std::cout << "I am derived class" << std::endl;
}
void f3()
{
A::f1();
}
};
int main()
{
B b;
b.f3();
return 0;
}
The output above is
I am derived class
The limitation I have here is that I can't change class A in any way.
Another limitation is that f2() needs to be called through f1(). A::f3() cannot call f1(). The call to f1() needs to be made to A since A's f1() does other things and B cannot override it.
Is there a way to force A::f2() be called when B::f3() is called? In other words, when we ask for the base version, how do we enforce all other functions called within the base class, to use the base version. In this example, that would be f2().
The question marked as duplicate is simply asking to call a parent function from a derived function with no other functions in the called function that overwritten.
Please note that a static cast of A to call f1 will result in the derived class's f2 function to be called.

How indexing within the virtual table is decided in c++?

Consider the below code.
#include<iostream>
using namespace std;
class Base
{
public:
virtual void function1() {cout<<"Base:function1()\n";};
virtual void function2() {cout<<"Base:function1()\n";};
};
class D1: public Base
{
public:
virtual void function1() {cout<<"D1:function1()\n";};
virtual void function2() {cout<<"D1:function2()\n";};
};
int main()
{
Base *ptr= new D1;
ptr->function1();
ptr->function2();
return 0;
}
The ptr will be pointing to D1 obj.
so whenever i call ptr->function1(), the function address is fetched from virtual table of class D1. It works same way for ptr->function2() as well.
In this case the vtable[0] will have function pointer to function1(), vtable[1] will have function pointer to function2().
My question is how function call to vtable index mapping happens?
How ptr->function1() & ptr->function2() indexes to vtable[0] & vtable[1] respectively?
The first element of the class is usuaylly the (hidden) vtable pointer - vptr. For a polymorphic class, the vtable is first initialized to the vtable of base class in the base class constructor. Then, when the derived class constructor executes the same vtable pointer is initialized to point to the derived class vtable. Note that the base class vtable points to base version of function1 and function2 whereas derived class vtable points to derived version of function1 and function2.
Now, when a pointer to base class points to an instance of derived class, this is what 'typically may' happen:
class base
{
//int* vptr; //hidden vtable pointer, created by compiler for polymorphic class. vptr points to base class vtable for base clas objects
public:
virtual void function1(){std::cout <<"base::function1()"<<std::endl;}
virtual void function2(){std::cout <<"base::function2()"<<std::endl;}
};
class derived: public base
{
//int* vptr; //hidden vtable pointer, inherited from the base class. vptr points to derived class vtable for derived class objects
public:
virtual void function1(){std::cout <<"derived::function1()"<<std::endl;}
virtual void function2(){std::cout <<"derived::function2()"<<std::endl;}
};
int main()
{
typedef void (*vtableFnPtr)();
base* pBase;
base base_obj;
derived derived_obj;
pBase = &derived_obj; //base pointer pointing to derived object
//one of the several possible implementations by compiler
int* vtableCallBack = *(int**)&derived_obj; //read the address of vtable pointed by the hidden vptr in the derived_obj
//pBase->function1();
((vtableFnPtr)vtableCallBack[0])(); //calls derived::function1(), when application calls pBase->function1();
//pBase->function2();
((vtableFnPtr)vtableCallBack[1])(); //calls derived::function2(), when application calls pBase->function2();
pBase = &base_obj;
//one of the several possible implementations by compiler
vtableCallBack = *(int**)&base_obj; //base pointer pointing to base object
//pBase->function1();
((vtableFnPtr)vtableCallBack[0])(); //calls base::function1(), when application calls pBase->function1();
//pBase->function2();
((vtableFnPtr)vtableCallBack[1])(); //calls base::function2(), when application calls pBase->function2();
}
Note that the C++ compiler does not say anything about the implementation methodology to be used for achieving polymorphic behavior and hence it is completly upto the compiler to use vtable or any other implementation as long as the behavior is polymorphic. However, vtable remains one of the most widely used methods to achieve polymorphic behavior.
"All problems in computer science can be solved by another level of indirection"
I referred to excellent and detail blog post and have tried below to explain use of vtable for your simple example. See if you are read thorough it.
struct Base;
// enumerates all virtual functions of A
struct table_Base {
void (*function1)(struct Base *this);
void (*function2)(struct Base *this);
};
struct Base {
const struct table_Base *pvtable; // table maintains pointers to virtual functions. Eventually to implementations
int data;
};
void Base_function1(struct Base *this) {
std::cout << "Base:function1()" << std::endl;
}
void Base_function2(struct Base *this) {
std::cout << "Base:function2()" << std::endl;
}
// table data for Base
static const struct table_Base table_Base_for_Base = { Base_function1, Base_function2};
void Base_Ctor(struct Base *this) {
this->pvtable = &table_Base_for_Base;
this->data = 1;
}
// Now for class D1
struct D1;
struct table_D1 {
void (*function1)(struct D1 *this);
void (*function2)(struct D1 *this);
};
struct D1 {
struct Base base;
const struct table_D1 *pvtable;
int more_data;
};
void D1_function1(struct D1 *this) {
std::cout << "D1:function1()" << std::endl;
}
void D1_function2(struct D1 *this) {
std::cout << "D1:function2()" << std::endl;
}
// Important functions that do re-direction
void D1Base_function1(struct Base *this) {
D1_function1((struct D1*) this);
}
void D1Base_function2(struct Base *this) {
D1_function2((struct D1*) this);
}
// table data for D1
static const struct table_D1 table_D1_for_D1 = {D1_function1, D1_function2};
// IMPORTANT table
static const struct table_Base table_Base_for_D1 = {D1Base_function1, D1Base_function2};
// Constructor for derived class D1
void D1_Ctor(struct D1 *this)
{
Base_Ctor(&this->base); // Base class vtable is initialized.
// Now, Override virtual function pointers
this->base.vtbl = &table_Base_for_D1; // Replace the vtable
this->mode_data = 100;
}
Internally this is the logic followed by the compiler to achieve correct behavior for virtual functions.
ptr->function1();
ptr->function2();
You can trace the method calls above using vtable logic explained and see if it works.

Inheriting the virtual specifier of base class's member function

The following code is based on the example on page 298 of C++ Templates: the Complete Guide. I removed the parts not relevant to my question.
class Virtual {
public:
virtual void foo() {
}
};
class Base : private Virtual {
public:
void foo() {
std::cout << "Base::foo()" << '\n';
}
};
class Derived : public Base {
public:
void foo() {
std::cout << "Derived::foo()" << '\n';
}
};
int main()
{
Base *p = new Derived;
p->foo(); // calls Derived::foo()
}
I do not understand how the call p->foo() ends up calling Derived::foo. More concretely, the static type of p is Base*. Base::foo is non-virtual. Now, Base privately inherits from 'Virtual', which has its own foo and it looks as if Base::foo somehow gets the virtual specifier from Virtual::foo. What is actually going on here?
The virtualness of foo is inherited from the base class Virtual.
In fact, writing virtual in Derived::foo will be superfluous and many developers will omit it. You cannot undo virtualness once you've marked that function as virtual in a base class.
You can force a call of Base::foo by writing p->Base::foo(); but that's an ugly contrivance.

Why is initialization of derived class through a base class pointer different from that through a derived class pointer?

#include <iostream>
using namespace std;
class Base {
public:
void F(){cout << "Base::F" << endl;};
virtual void G(){cout << "Base::G" << endl;};
};
class Derived : public Base {
public:
void F(){cout << "Derived::F" << endl;};
void G(){cout << "Derived::G" << endl;};
};
int main(){
Derived *pDerived = new Derived;
pDerived->F(); //F was redefined
pDerived->G(); //G was overriden
Base *pBase = new Derived;
pBase->F();
pBase->G();
}
The output of this code is:
Derived::F
Derived::G
Base::F
Derived::G
Why does not the code produce the following output?
Derived::F
Derived::G
Derived::F
Derived::G
i.e. When a derived class object is initialized through a base class pointer, why is the function definition for a non-virtual function different from that of a derived class object initialized through a derived class pointer? Shouldn't the same type of object be initialized when we call "new Derived" whether it be from a base class pointer or a derived class pointer?
The function F() is not virtual, which means that the function call will be statically dispatched to the version in the static type of the pointer/reference, rather than let it find at runtime what the dynamic type of the object really is.
You can access the same function from a pointer to Derived if you qualify which variant you are interested in:
pDerived->Base::F();

Segmentation fault from function call in destructor

Why does this code compile and correctly print "Derived"?
template <class Derived>
class Base
{
public:
Base(Derived& d) : derived(d) {}
void f() { std::cout << "Base\n"; }
virtual ~Base() { derived.f(); }
private:
Derived& derived;
};
class Derived : public Base<Derived>
{
public:
Derived() : Base<Derived>(*this) {}
void f() { std::cout << "Derived\n"; }
};
int main()
{
Derived d;
}
But either making Base::f virtual or both Derived::f and Base::f virtual causes "Base" to be printed. Also, changing Derived::f to virtual gives a Invalid memory reference (SIGSEGV). I would expect those two other cases to print "Derived" since I'm calling it from a Derived instance.
Why does this happen?
This is a dangling reference.
You initialize the field Base::derived to be a reference to the Derived object via the Derived constructor, but then you access it in the Base destructor after the Derived object has been destroyed.
Access any object after it has been destroyed (via either pointer or reference) is undefined behavior, so anything might happen.