Reputation: 2096
#include <iostream>
template <typename T>
class A {};
template <typename T>
class B : public A<T> {};
class C
{
virtual A<int> func() = 0;
};
class D : public C
{
virtual B<int> func() override
{
return B<int>{};
}
};
Here B
inherits from A
and the template argument is int
for both of the return values. Why can't I just return B<int>
instead of A<int>
?
Upvotes: 0
Views: 692
Reputation: 56
From cppreference:
If the function
Derived::f
overrides a functionBase::f
, their return types must either be the same or be covariant.
There are 3 conditions to be all satisfied for two types to be covariant, and one of them is that they need to be either a pointer type or a reference type.
A<int>
and B<int>
are neither the same type nor covariant types, which implies that you cannot use B<int>
as the return type of your overridden method.
Please also notice that you don't have to use virtual
specifier in your overridden method.
Moreover, as also other people noticed, the following will work and return an A<int>
-typed object:
A<int> func() override
{
return B<int>{};
}
But you should avoid it. In fact, after a B<int>
object is created, it will be sliced into an A<int>
type, for the reasons we have seen, meaning your object type will effectively be simply A<int>
, and not a B<int>
's instance. This means that you uselessly created a B<int>
instance when you could have just created an A<int>
.
If you need a B<int>
, you'll need to return either a pointer or a reference.
Upvotes: 1
Reputation: 364
B D::func() cannot be an override of AC::func(), because the return type of those two function are different from each other.
Upvotes: 1
Reputation: 855
When declaring B, you must inherit from an actual class, not a template:
template <typename T>
class B : public A<T> {};
The second issue is that you cannot change the signature of func()
when overriding it in class D
. However, once that's fixed, you will be able to return B<int>{}
as expected.
Edit: a third problem pointed out by @Josh Wilson is that you will not get the behavior of a B
from the return value of func()
because it specifies an A
returned by value. You need to return a pointer to A<int>
for polymorphism to apply.
Upvotes: 1
Reputation: 2679
As merlinND pointed out, you have to inherit from class A<T>
. But it will still fail unless you return a pointer or reference to B instead of a value type. The following will compile.
#include <iostream>
template <typename T>
class A {};
template <typename T>
class B : public A<T> {};
class C
{
virtual A<int>* func() = 0;
};
class D : public C
{
virtual B<int>* func() override
{
return new B<int>{};
}
};
Upvotes: 1