C++ 函数无法使用模板为基类的子类派生模板
c++ function cannot derive template for child class of base class with templates
我对模板有点陌生,当我以设置模板的方式从基类继承时,我不明白编译器如何派生子类的模板。
我正在创建一个遗传算法基类,我已经为种群的个体编写了一个抽象基类。我想有一个通用的定义,所以我使用模板来定义胎儿型和基因型:
template<typename T, typename S>
class individual {
public:
individual(S& fenotyp, T& genotyp) :
fenotype(fenotyp), genotype(genotyp) {}
...
S fenotype;
T genotype;
...
};
当个体是位字符串时,我有以下子类:
class bitstring_individual : public individual<boost::dynamic_bitset<>,
boost::dynamic_bitset<>> {
public:
using individual::individual;
...
};
现在我不再需要使用模板括号了。再往下看,我有一个函数,给定一个人口std::vector<individual<T,S>>
,返回适应度最高的一半。这适用于任何类型的个人,因此我们可以保持定义通用:
template<typename T, typename S>
std::vector<individual<T,S>> select_best_half(std::vector<individual<T,S>> parents,
std::vector<individual<T,S>> children) {
...
}
但是,如果我调用此函数,我会得到error: no matching function for call to select_best_half(...)
,编译器说template argument deduction/substitution failed:
和mismatched types ‘individual<T, S>’ and ‘bitstring_individual'
。
在bitstring_individual
的定义中,我们看到:
bitstring_individual : individual<boost::dynamic_bitset<>,boost::dynamic_bitset<>>
那么为什么编译器不明白模板应该boost::dynamic_bitset<>
呢?有人可以帮助我了解编译器如何处理此继承以及如何修复它吗?
(using bitset = boost::dynamic_bitset
(
您的bitstring_individual
与individual<bitset, bitset>
不同,编译器理所当然地无法识别它们。一个继承另一个,是的,但这并不能使它们在任何地方都可以互换 - 特别是当用作模板参数时。
简而言之:不同(甚至多态相关(类型的向量(和其他容器(不是协变的。就像您不能将std::vector<int>
传递给期望std::vector<long>
的函数一样,您也不能传递期望std::vector<individual<bitset, bitset>>
的std::vector<bitstring_individual>
。
注意:是的,它们是不同的转换,但想法是相同的。
想象一下,sizeof(individual<bitset, bitset>) = 32
和bitstring_individual
添加了一些成员,以便sizeof(bitstring_individual) = 48
.如果编译器推导出T = S = bitset
,那么它将生成一个包含std::vector<individual<bitset, bitset>>
的方法签名,因此一个元素大小为 32 的向量。但是当你尝试调用它时,你正在传递一个元素大小为 48 的向量。这些向量不是协变的,这总是会导致问题。
如果您希望您的具体个人除了模板化基类提供的功能之外没有其他功能,只需执行以下操作:
using bitstring_individual = individual<bitset, bitset>;
否则,您的向量无法直接存储个体 - 您必须对所有种群向量使用std::vector<std::shared_ptr<individual<T, S>>>
之类的东西(或者unique_ptr
或ref
而不是shared_ptr
(。
你的问题实际上涉及C++中(某些(类型的协方差和逆变。即使您要对模板参数进行"硬编码",即具有:
using i_bs_bs = individual<bitset, bitset>;
using std::vector;
class bitstring_individual : public i_bs_bs { ... };
vector<bsi> select_best_half(vector<i_bs_bs> parents, vector<i_bs_bs> children) {
...
}
您仍然会收到将vector<bitstring_individual>
传递给select_best_half()
的错误。为什么?因为,在C++std::vector<T>
中不是协变类型构造函数。
以链接到维基百科页面为例,假设您的继承类是Animal
(基类(和Cat
(派生类(。在C++中,您无法将动物添加到猫的载体中。该向量的所有元素都需要是猫。类似地,正如@MaxLanghof的回答所解释的那样,你不能向元素是bitstring_individual
基类型的向量添加bitstring_individual
。处理bitstring_individual
所需的任何特殊行为都不适用于vector<i_bs_bs>
的元素。
- C++ 继承:将子类传递给需要基类的函数并获取子类行为
- 使用子类覆盖基类中定义的函数
- 子类地址等于虚拟基类地址?
- 将子类方法声明为基类的友元
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 文本冒险游戏 - 如何区分一种项目类型与另一种项目类型以及如何构建项目类/子类
- 如何将子类作为函数的参数传递给期望基类,然后将该对象传递到指向这些抽象类对象的指针向量中?
- 如何访问基类向量中的子类变量?(对于实体组件系统)
- 如何使基类从子类调用覆盖函数
- 如何调用传递给 JNI 'jobject' 的 Java 对象的子类/子类的方法
- 模型类/子类,其中子类类型在C++中先验未知
- 具有虚拟析构函数的基类子类中的默认析构函数
- 使用默认构造函数的父类;子类的析构函数意外调用
- Qt c++ 类 + 子类使用 Q_OBJECT 不起作用
- 提升 Python 包装的虚拟类 - 子类返回错误:与C++签名不匹配
- 宠物动物园C++/继承类/子类
- C++ 继承基和子类
- 模板基类子类的模板专用化
- 在c++中,如何确定一个类是否是继承链中的最后一个类/子类?它位于基类的另一端
- 如何使用模板类的模板类子类从哈希表实现哈希集