C++: how to reuse code in covariant return types?
-
06-07-2021 - |
Question
I have the following simple class
class base
{
public:
int x;
base &set(int y)
{
x = y;
return *this;
}
};
and want to create a new one with added functionality, say to print the value x. So I do:
class derived : public base
{
public:
void print()
{
cout << x << endl;
}
};
Now in the main program I want to do something like
D.set(2).print();
for which however the compiler complains that class base has no member named 'print'.
If I try to use covariant return types and write the two classes as
class base
{
public:
int x;
virtual base &set(int y)
{
x = y;
return *this;
}
};
class derived : public base
{
public:
derived &set(int y)
{
x = y;
return *this;
}
void print()
{
cout << x << endl;
}
};
then the statement works just fine, but I was forced to rewrite the exact same function body for 'set' in both classes, even though the only thing that changes is the return type.
If later on I need to change the functionality of base::set then I will have to go through all the derived classes to change the 'set' function... are there any ways to avoid that? Thanks in advance!
Solution
C++ work as you say, and you say in your base class set
return base&
, so that is what C++ do. But in order to solve this you have many ways.
First you are not forced to make a function virtual
to override it in a derived class (note that virtual call are slightly slower than normal calls).
Second you can refer to base class implementation as base::set
so the code will be as follow:
class base {
...
base& set( int x ) {...}
};
class derived : public base {
derived& set( int x ) {
return static_cast<derived&>( base::set(x) );
}
};
OTHER TIPS
Depending on your circumstances, you might be able to use the CRTP:
template <class D>
class base {
D& set(int x) {
…;
return *static_cast<D*>(this);
}
};
class derived : base<derived> { … };