In the following code I return a derived class CDerived
by-value from a function returning its base class, CBase
.
For example purposes, CDerived
contains a _number
field, and I understand that this is "sliced" off during its conversion to the by-value return type, CBase
.
However, what confuses me here is that the virtual function Print
somehow gets transmuted into its base-class version. In this case the v-table hasn't simply been sliced, it's been altered.
In my actual code _number
does not exist, nor does any other data. I would like to be able to return a derived class only for it's v-table, which is declared by the base.
From this question I see that I can "work around" this particular issue by returning a function pointer (or I suppose crafting my own v-table), but why is the v-table being altered in the first place, and is there any way to get around this alteration?.
#include <iostream>
class CBase
{
public:
virtual void Print() { std::cout << "CBase" << std::endl; }
};
class CDerived : public CBase
{
int _number;
public:
explicit CDerived(int n) : _number(n) { }
virtual void Print() override { std::cout << "CDerived" << std::endl; }
};
CBase GetBase()
{
return CDerived(42);
}
int main()
{
CBase base = GetBase();
base.Print(); // Outputs CBase
return 0;
}
That's how C++ works.
You don't return a CDerived
object, you return a CBase
, copied from the CBase
sub-object of the temporary CDerived
.