是否有相当于Java <?在C++中扩展ClassName>?

Sca*_*cab 5 c++ java inheritance templates

我正在查看这个https://docs.oracle.com/javase/tutorial/java/generics/subtyping.htmlhttps://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;
}
Run Code Online (Sandbox Code Playgroud)

我理解为什么它在C++中不起作用.在Java中,解决方案是使用以下构造:

List<? extends Integer> intList = new ArrayList<>();
List<? extends Number>  numList = intList;  // OK. List<? extends Integer> is a subtype of List<? extends Number>
Run Code Online (Sandbox Code Playgroud)

(给定它IntegerNumber示例链接中指出的子类).

使用:

template <typename U>
void farmTest(const AnimalFarm<U *> &farm);
Run Code Online (Sandbox Code Playgroud)

可能是解决方案,但有没有更好的方法在C++中做到这一点而不会失去Cat或Dog从Animal继承的事实(作为Integer一个子类型Number)?

谢谢.

Sto*_*ica 5

如果你的最终游戏是在和之间形成一个is-a关系,那么一些具有类型特征的模板专业化可以做到这一点.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*>
{
};
Run Code Online (Sandbox Code Playgroud)

由于AnimalFarm<Animal*>成为公共基础AnimalFarm<Dog*>,函数参数引用将绑定到它.虽然您应该注意到相应的层次结构是平的,无论它有多深Animal.

你可以看看live.