C++派生类纯虚函数实现:如何复用基API实现类构建顶级API?
你遇到的是典型的「接口继承+实现复用」场景,要让imp_top既满足api_top的抽象接口要求,又能直接用上imp_base里写好的foo(),我给你两种靠谱的实现方式,你可以根据代码环境选择:
方案一:多重继承+虚拟继承(代码更简洁,推荐)
首先得调整一下api_top的继承方式——因为后续我们要让imp_top同时继承api_top和imp_base,为了避免C++里的菱形继承问题(也就是api_base被重复实例化),需要给api_top的继承加个virtual关键字:
class api_base { public: virtual int foo() = 0; }; // 这里添加virtual,使用虚拟继承api_base class api_top : public virtual api_base { public: virtual int bar() = 0; };
接下来写imp_top就很简单了,直接多重继承api_top(接口)和imp_base(实现),然后只需要实现api_top要求的bar()就行——imp_base的foo()会自动覆盖api_base的纯虚函数:
class imp_base { public: int foo() { return 1; } }; class imp_top : public api_top, public imp_base { public: // 只需要实现api_top定义的纯虚函数bar() int bar() override { return 2; // 这里替换成你的具体业务逻辑 } // 可选:如果担心命名冲突,可以显式指定使用imp_base的foo // using imp_base::foo; };
验证功能
用这段代码测试是否正常工作:
#include <iostream> int main() { api_top* api_ptr = new imp_top(); std::cout << "foo() 返回值: " << api_ptr->foo() << std::endl; // 输出1,来自imp_base的实现 std::cout << "bar() 返回值: " << api_ptr->bar() << std::endl; // 输出2,来自imp_top的实现 delete api_ptr; return 0; }
方案二:组合模式(适合无法修改原有接口的场景)
如果因为某些原因你不能修改api_top的继承结构(比如它是第三方库的代码),那用组合的方式更稳妥:让imp_top内部持有一个imp_base的实例,然后在foo()里转发调用imp_base的实现:
class imp_top : public api_top { private: imp_base base_impl; // 组合imp_base的实例 public: // 转发foo()调用到imp_base的实现 int foo() override { return base_impl.foo(); } // 实现api_top要求的bar() int bar() override { return 2; } };
这种方式不需要修改任何原有基类的代码,兼容性更好,唯一的小缺点是要写一行转发代码。
补充:为什么方案一需要虚拟继承?
简单来说就是避免「重复继承」的坑:如果不用虚拟继承,imp_top里会存在两个api_base的实例(一个来自api_top,一个来自imp_base的隐式关联),这样imp_base的foo()就没法正确覆盖api_base的纯虚函数,编译器会报错说imp_top仍是抽象类。虚拟继承能确保整个继承链里只有一个api_base实例,让实现和接口正确对接。
内容的提问来源于stack exchange,提问作者Adrian

