I've been playing around with template and inheritance but there is something strange about using virtual function members with template parameters when performing a cast to the base class. They seem to work using "direct inheritance" but not if I "defer" the inheritance later on.
A bit of code to illustrate:
Example [1]
struct CastExBase
{
virtual void f() {}
};
template<class RT>
struct CastExA : CastExBase
{
void f() {std::cout << "CastExA" << std::endl;}
virtual void g() {std::cout << "g - A" << std::endl;}
virtual RT h() {std::cout << "h - A" << std::endl;}
};
struct CastExB
{
void execF() {std::cout << "CastExB" << std::endl;}
void g() {std::cout << "g - B" << std::endl;}
int h() {std::cout << "h - B" << std::endl;}
};
struct CastExC :
public CastExA<int>,
protected CastExB
{
void f() override
{
(static_cast<CastExB*>(this))->execF();
}
void g() override
{
(static_cast<CastExB*>(this))->g();
}
};
Test case:
CastExBase* a2 = new CastExC();
CastExA<int>* a3 = (CastExA<int>*) a2;
a3->g(); // This prints g - B as expected
a3->h(); // This prints h - A ... why???
Why a3->h() does not print h - B?
I tried also another test directly inheriting from the base class and in this case it correctly works.
Example [2]
struct CastExDBase
{
};
template<class T>
struct CastExD : CastExDBase
{
virtual T f() {std::cout << "CastExD" << std::endl;}
};
struct CastExE : CastExD<int>
{
int f() {std::cout << "CastExE" << std::endl;}
};
Test case:
CastExDBase* d1 = new CastExE();
CastExD<int>* d2 = (CastExD<int>*) d1;
d2->f(); // This prints CastExE as expected
Is this related to UB?
Even if CastExC
inherits both CastExA<int>
and CstExB
, the definition of h()
in CstExB
will not override the "definition" of h()
in CastExA<int>
because CastExA<int>
and CstExB
are not related. If you try to do this:
CastExBase* a2 = new CastExC();
CastExC* a3 = (CastExC*) a2;
a3->h();
You will get an ambiguous request for h()
. If you want to overload, you need to do this manually:
struct CastExC: protected CastExB, public CastExA<int> {
virtual int h() override { return CastExB::h(); }
};
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