前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >c++ template 多层继承下找不到纯虚拟函数实现 报错:undefined reference to "xxx"

c++ template 多层继承下找不到纯虚拟函数实现 报错:undefined reference to "xxx"

作者头像
10km
发布2022-05-07 09:59:30
2940
发布2022-05-07 09:59:30
举报
文章被收录于专栏:10km的专栏10km的专栏

如下代码中,定义了3个类,ClassA,ClassB,ClassC,依次为被继承关系,ClassA,ClassB是模板类, 在ClassA中定义了一个纯虚拟函数getKeyFromObject,实现将从V中获取K的功能: getKeyFromObject函数在ClassA,ClassB中都有被调用,在ClassC中被实现。 按照我的思路,这样就成了。不论在Class,ClassB中,都会调用ClassC中的getKeyFromObject来实现V->K的转换。

代码语言:javascript
复制
//抽象类模板(第一层)
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;
    }
}

然而编译连接的时候,却报错了

代码语言:javascript
复制
 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(第二层)代码,修改后的代码是这样:

代码语言:javascript
复制
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;//再次定义为纯虚函数
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015-10-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档