带默认实现的多重继承失效:被迫始终重写默认实现
看起来你在插件SDK的接口设计里碰到了个头疼的问题:基础接口写了默认实现,但子接口的实现类却没法复用,被迫每次都重写。我之前做SDK接口设计时也遇到过类似情况,大概率是C++的虚函数继承规则和多重继承的特性在搞鬼,给你梳理下核心原因和解决办法:
一、先检查你的接口定义是不是踩了这些坑
1. 子接口是不是误把基础接口的函数改成纯虚了?
如果你的子接口是这么写的:
class ISubProfile : public IMasterProfile { public: // 踩坑!这里重新声明成纯虚,直接覆盖了基础接口的默认实现 virtual Uint16 getSomeValue() = 0; };
这种情况下,ISubProfile会把IMasterProfile里的默认实现给“抹掉”,强制所有实现类必须重写这个方法——哪怕你本来只想复用基础逻辑。
修复方式:除非你明确要求子接口的实现类必须重写某个方法,否则子接口里别重复声明基础接口的虚函数。
2. 基础接口的默认实现写法是不是不对?
C里纯虚函数(带=0的)虽然C11后允许加默认实现,但编译器支持不一,而且很容易搞混。你的基础接口应该把需要提供默认实现的函数写成普通虚函数,纯虚函数留给必须实现的方法:
class DYNAMIC_ATTRIBUTE IMasterProfile : public IVWUnknown { public: // 正确写法:普通虚函数+默认实现,子类可重写可复用 virtual Uint16 getSomeValue() { return 0; // 默认逻辑 } // 必须实现的方法,写成纯虚 virtual void mustImplement() = 0; };
二、多重继承下复用默认实现的正确姿势
如果你的实现类同时继承了多个子接口(比如ISubProfileA和ISubProfileB都继承自IMasterProfile),大概率会碰到菱形继承的歧义问题,这时候得这么处理:
1. 显式调用基础接口的默认实现
如果实现类不想重写,直接复用基础逻辑,可以在方法里显式指定作用域:
class ProfileImpl : public ISubProfileA, public ISubProfileB { public: // 直接复用IMasterProfile的默认实现 Uint16 getSomeValue() override { return IMasterProfile::getSomeValue(); } // 实现必须重写的纯虚方法 void mustImplement() override { // 你的业务逻辑 } };
2. 用虚拟继承解决菱形继承歧义
如果多个子接口都继承自IMasterProfile,给子接口加上virtual关键字做虚拟继承,确保基础接口在实现类里只有一个实例,避免调用歧义:
// 子接口用虚拟继承基础接口 class ISubProfileA : virtual public IMasterProfile { // 子接口的额外方法 }; class ISubProfileB : virtual public IMasterProfile { // 子接口的额外方法 }; // 实现类继承子接口,此时IMasterProfile只有一个实例 class ProfileImpl : public ISubProfileA, public ISubProfileB { public: // 现在不重写getSomeValue的话,会自动用IMasterProfile的默认实现 void mustImplement() override { // 你的业务逻辑 } };
三、如果SDK必须保持子接口的现有结构
要是因为SDK规范要求,子接口必须重新声明基础接口的方法,那可以让子接口直接调用基础实现,把默认实现“传递”下去:
class ISubProfile : public IMasterProfile { public: // 子接口声明方法,但直接复用基础实现 Uint16 getSomeValue() override { return IMasterProfile::getSomeValue(); } // 子接口要求必须实现的额外方法 virtual void subSpecificMethod() = 0; };
这样实现类继承ISubProfile后,只需要重写subSpecificMethod和mustImplement,getSomeValue自动复用基础逻辑。
内容的提问来源于stack exchange,提问作者prom85

