如下代码中,定义了3个类,ClassA,ClassB,ClassC,依次为被继承关系,ClassA,ClassB是模板类,
在ClassA中定义了一个纯虚拟函数getKeyFromObject,实现将从V中获取K的功能:
getKeyFromObject函数在ClassA,ClassB中都有被调用,在ClassC中被实现。
按照我的思路,这样就成了。不论在Class,ClassB中,都会调用ClassC中的getKeyFromObject来实现V->K的转换。
//抽象类模板(第一层)
template<typename K, typename V>
class ClassA_Abstract {
public:
void test(V* obj){
getKeyFromObject(obj);//调用纯虚拟函数
}
protected:
/*纯虚拟函数,子类必须实现*/
virtual K* getKeyFromObject(V* obj)=0;
}
//抽象类模板(第二层)
template<typename K,typename V>
class ClassB_Abstract: public ClassA_Abstract <K, V> {
void test2(V* obj){
//在这里指定是调用父类的函数,要加上ClassA_Abstract <K, V>::
ClassA_Abstract <K, V>::getKeyFromObject(obj);//调用纯虚拟函数,
}
}
//普通实现类(第三层)
template<typename K>
class ClassC: public ClassB_Abstract<CKeyObj, CValueObj> {//CKeyObj, CValueObj为实际的对象
void test3(V* obj){
ClassA_Abstract <K, V>::getKeyFromObject(obj);
}
//实现纯虚拟函数
CKeyObj* getKeyFromObject(CValueObj*obj){
std::cout<<"ClassC::getKeyFromObject"<<endl;
return &obj->key;
}
}
然而编译连接的时候,却报错了
ClassB_Abstract.h:undefined reference to `ClassA_Abstract <CKeyObj, CValueObj>::getKeyFromObject(CValueObj*)'
报错的位置在ClassB的test2()方法,这一行:
ClassA_Abstract <K, V>::getKeyFromObject(obj);
显然,ClassA_Abstract <CKeyObj, CValueObj>::getKeyFromObject(CValueObj*)
是个纯虚函数,
但编译器没有找到在ClassC中定义的getKeyFromObject的实现,为什么呢?
编译器在遇到纯虚拟函数时,会从父类开始一层层向下寻找,如果在子类中找到该函数,但还是被定义为纯虚函数,则会继续向子类的子类中寻找。如果子类中没有定义该函数,就中断查找过程。即使子类的子类中有实现该纯虚拟函数,也找不到。
上面的ClassB(也就是第二层)中没有定义这个纯虚拟函数。所以即使ClassC(第三层)中实现了该函数,编译也会报错。
知道原因,就好解决了:
在ClassB中再定义一次该函数,同样申明成纯虚函数,并且在第二层调用的时候,不能指定调用父类的函数
只需要修改ClassB(第二层)代码,修改后的代码是这样:
template<typename K,typename V>
class ClassB_Abstract: public ClassA_Abstract <K, V> {
void test2(V* obj){
getKeyFromObject(obj);
//去掉ClassA_Abstract <K, V>::
}
virtual K* getKeyFromObject(V* obj)=0;//再次定义为纯虚函数
}