我正在看这个https://docs.oracle.com/javase/tutorial/java/generics/subtyping.html和 https://docs.oracle.com/javase/tutorial/java/generics/inheritance.html并问自己如何用 C++ 实现它。
我有这个小例子来说明:
#include <iostream>
class Animal
{
public:
virtual std::string type() const = 0;
virtual ~Animal() {}
};
class Dog : public Animal
{
public:
virtual std::string type() const {
return "I am a dog";
}
};
class Cat : public Animal
{
public:
virtual std::string type() const {
return "I am a cat";
}
};
template <typename T>
class AnimalFarm
{
};
void farmTest(const AnimalFarm<Animal *> &farm)
{
std::cout << "test farm";
}
int main(int argc, char *argv[])
{
AnimalFarm<Dog *> dogFarm;
AnimalFarm<Animal *> animalFarm;
farmTest(animalFarm); // OK
farmTest(dogFarm); // NOK compiler error as class AnimalFarm<Dog *> does not inherits from class AnimalFarm<Animal *>
return 0;
}
我明白为什么它在 C++ 中不起作用。在 Java 中,解决方案是使用以下构造:
List<? extends Integer> intList = new ArrayList<>();
List<? extends Number> numList = intList; // OK. List<? extends Integer> is a subtype of List<? extends Number>
(假设 Integer
是示例链接中指出的 Number
的子类)。
使用:
template <typename U>
void farmTest(const AnimalFarm<U *> &farm);
可能是解决方案,但有没有更好的方法在 C++ 中做到这一点,同时又不丢失 Cat 或 Dog 从 Animal 继承的事实(因为 Integer
是 Number
的子类型)?
谢谢。
最佳答案
如果您的最终目标是在 AnimalFarm<Dog *>
之间形成是关系和 AnimalFarm<Animal *>
, 那么一些具有类型特征的模板特化就可以做到这一点。
template <typename T, typename = void>
class AnimalFarm // Primary template
{
};
template<typename T>
class AnimalFarm<T*,
std::enable_if_t<
!std::is_same<T, Animal>::value &&
std::is_base_of<Animal, T>::value
>
> // Specialization only instantiated when both conditions hold
// Otherwise SFINAE
: public AnimalFarm<Animal*>
{
};
自 AnimalFarm<Animal*>
成为AnimalFarm<Dog*>
的公共(public)基地,函数参数引用将绑定(bind)到它。尽管您应该注意到相应的层次结构是扁平的,无论 Animal
有多深一个去。
你可以看看 live .
关于java - 是否有等同于 Java <?在 C++ 中扩展 ClassName>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47979349/