I create two simple classes by inheritance, and I add a virtual function and the override in the child class.
class Base
{
public:
virtual Base* getThis() { std::cout << "called Base::getThis()\n"; return this; }
virtual void func1() { std::cout << "called Base::func1\n"; }
};
class Derived : public Base
{
public:
Derived* getThis() override { std::cout << "called Derived::getThis()\n"; return this; }
void func1() override { std::cout << "called Derived::func1\n"; }
void func2() { std::cout << "called Derived::func2\n"; }
};
With c covariance, I can do this:
int main()
{
Derived d{};
Base* b{ &d };
b->getThis()->func1();
return 0;
}
Now, I would like to call Derived::func2
.
b->getThis()->func2();
The previous code produces the following error: error: 'class Base' has no member named 'func2';
The only solution I have:
dynamic_cast<Derived*>(b->getThis())->func2();
Do we have to use dynamic_cast
or static_cast
, to call Derived::func2
?
Is there another method?
CodePudding user response:
Do we have to use dynamic_cast or static_cast, to call Derived::func2?
Yes.
Is there another method?
Declare a virtual Base::func2
function.
To clarify about covariance, it makes this possible:
Derived d{};
d->getThis()->func2();
Without covariance, Derived* Derived::getThis
wouldn't be allowed and thus the above wouldn't work.
CodePudding user response:
Covariant return types are merely a trick that allows the Liskov Substitution Principle to work while varying the return type in the derived class interface slightly. But the point of LSP remains: the base class interface is the interface. It's not a way to make a base class transparently provide stuff that's exclusively part of the derived class.
If you have a pointer/reference to the base class, calling getThis
though that pointer/reference will always return a Base*
. If you want to get at some derived class-only elements, you must always use some kind of cast.