编译器为何将ParameterExpr类判定为抽象类?
这是C++菱形继承的经典坑!我来给你掰明白问题所在
嘿,你的代码里其实藏着一个典型的菱形继承问题,这就是编译器把ParameterExpr判定为抽象类的核心原因:
先拆解你的继承结构
你这是标准的菱形继承链:
- 最顶层是抽象类
IMetaExpression,包含纯虚函数get_type() Expr继承IMetaExpression,并实现了get_type()IParameterExpression也继承IMetaExpression,新增了纯虚函数get_parameter()- 最后
ParameterExpr同时继承Expr和IParameterExpression
问题的核心:非虚拟继承导致的重复基类实例
C++默认的继承是非虚拟继承,这意味着ParameterExpr对象内部会包含两个完全独立的IMetaExpression子对象:一个来自Expr分支,一个来自IParameterExpression分支。
虽然Expr实现了get_type(),但它只覆盖了自己分支里那个IMetaExpression的纯虚函数;而IParameterExpression分支里的IMetaExpression的get_type()仍然是未实现的纯虚状态。编译器检测到类里还有未完成的纯虚函数,自然就判定ParameterExpr是抽象类,不允许实例化。
解决方法:用虚拟继承合并重复基类
只需要把Expr和IParameterExpression对IMetaExpression的继承改成虚拟继承,就能让整个继承体系里只存在一个IMetaExpression实例。这样Expr实现的get_type()就能覆盖这个唯一的纯虚函数,ParameterExpr也就不再是抽象类了。
修改后的代码如下:
class IMetaExpression { public: virtual int get_type(void) = 0; virtual ~IMetaExpression(){} }; // 加上virtual关键字,虚拟继承IMetaExpression class IParameterExpression : public virtual IMetaExpression { public: virtual char get_parameter(void) = 0; }; // 同样加上virtual class Expr : public virtual IMetaExpression { public: virtual int get_type(void) override { return 0; } }; class ParameterExpr : public Expr, public IParameterExpression { public: virtual char get_parameter(void) override { return 'c';} }; int main() { auto p = new ParameterExpr(); p->get_type(); delete p; return 0; }
内容的提问来源于stack exchange,提问作者Alex Aparin
相关产品推荐
相关产品推荐

