C++:如何通过继承成员函数重写接口以消除抽象类
解决C++多重继承下接口方法未被基类实现覆盖的问题
你的问题核心在于菱形继承导致的重复基类实例,使得Select类无法复用From的leftJoin实现来满足ISelect继承链中的纯虚函数要求。
问题根源
你的类继承结构是:
IFrom是顶层纯虚接口,包含纯虚leftJoinISelect继承IFrom,新增纯虚fromFrom继承IFrom,实现leftJoinSelect同时继承ISelect和From
这种结构会让Select内部存在两个独立的IFrom子对象:一个来自ISelect的继承链,另一个来自From的继承链。From实现的leftJoin只覆盖了它自己继承的那个IFrom的纯虚函数,而ISelect继承的IFrom的leftJoin仍然是未实现的纯虚函数,所以Select被判定为抽象类,无法实例化。
解决方案:使用虚继承消除重复基类
通过虚继承让所有继承IFrom的子类共享同一个IFrom基类实例,这样From的leftJoin实现就能覆盖唯一的IFrom纯虚函数,同时Select实现ISelect的from方法后,就不再是抽象类。
修改后的代码如下:
1. 修改接口类的继承方式
// 顶层IFrom接口保持不变 class IFrom { public: virtual ~IFrom() = 0; virtual std::unique_ptr<IFrom> leftJoin( const IEntityAlias &entity_alias, const IColumnName &lhs_column_name, const IComparisonOperator &comp_operator, const IColumnName &rhs_column_name) = 0; }; inline IFrom::~IFrom() {} // ISelect改为虚继承IFrom class ISelect : public virtual IFrom { public: virtual ~ISelect() = 0; virtual std::unique_ptr<IFrom> from(const IEntityAlias &entity_alias) = 0; }; inline ISelect::~ISelect() {}
2. 修改实现类的继承方式(并修正笔误)
// From改为虚继承IFrom,同时修正构造函数的笔误(原代码中的Form是拼写错误) class From: public virtual IFrom { protected: std::shared_ptr<PostgreSQL> _SGBDR; std::string _current_query; public: From() = default; From(const std::shared_ptr<PostgreSQL> SGBDR, std::string &¤t_query); From(From &&o); // 修正原代码的Form为From From(const From &o) = delete; const From &operator=(const From &o) = delete; virtual ~From() = default; std::unique_ptr<IFrom> leftJoin( const IEntityAlias &entity_alias, const IColumnName &lhs_column_name, const IComparisonOperator &comp_operator, const IColumnName &rhs_column_name) override; }; // Select类无需修改继承方式,因为父类都已使用虚继承 class Select : public ISelect, public From { public: using From::From; using From::leftJoin; std::unique_ptr<IFrom> from(const IEntityAlias &entity_alias) override; };
验证你的预期调用
现在Select可以正常实例化,且满足你的调用需求:
// 正常实例化Select ISelect *select = new Select(); select->from(/* 传入对应参数 */); select->from(/* 传入对应参数 */)->leftJoin(/* 传入对应参数 */); select->leftJoin(/* 传入对应参数 */); // 注意方法名是leftJoin,和定义保持大小写一致 IFrom *from = new From(/* 传入对应参数 */); from->leftJoin(/* 传入对应参数 */); // from->from(); // 编译报错,符合预期,IFrom没有from方法
额外说明
虚继承会在对象中添加额外的虚基类指针,带来微小的性能开销,但对于ORM这种场景来说完全可以忽略。它解决了菱形继承中重复基类的问题,是C++中处理这类多接口继承场景的标准方案。
内容的提问来源于stack exchange,提问作者Alexis ROARD
相关产品推荐
相关产品推荐

