You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++派生类未正确重写抽象类方法引发编译错误的问询

编译错误解决:抽象类派生类的方法重写问题

我定义了抽象类BaseClass,其中包含一个接受BaseResult类型参数的run方法;派生类DerivedClassA继承自BaseClass,其run方法的参数为BaseResult的派生类DerivedResult。但编译时出现如下错误:

示例代码

#include <iostream>
#include <memory>
#include <vector>

struct BaseResult {
  virtual ~BaseResult() = default;
};

class BaseClass {
  public:

  virtual ~BaseClass() = default;

  virtual void impl(int test) = 0;

  virtual void run(BaseResult result) = 0;
};

struct DerivedResult : BaseResult {
  DerivedResult() {}
};

class DerivedClassA : public BaseClass {
  private:
  int custom = 0;

  public:

  DerivedClassA() {}

  static void run() {}

  void impl(int test) {
    std::cout << "A" << std::endl;
    std::cout << test << std::endl;
  }

  void run(DerivedResult result) {};

  ~DerivedClassA() = default;
};

int main() {
  std::vector<std::shared_ptr<BaseClass>> items;
  items.emplace_back(std::make_shared<DerivedClassA>());

  for (const auto& item : items)
    item->impl(5);

  return 0;
}

编译错误信息

error: no matching function for call to 'construct_at(DerivedClassA*&)'
error: invalid new-expression of abstract class type 'DerivedClassA'

问题原因与解决方法

核心原因

你没有正确重写基类的run方法,派生类中的void run(DerivedResult result)是一个重载方法,而非对基类virtual void run(BaseResult result)的重写。这导致DerivedClassA仍然未实现基类的纯虚函数,因此属于抽象类,无法被实例化(std::make_shared<DerivedClassA>会失败)。

解决方案

方案一:正确重写基类方法,处理参数类型

首先修改基类的run方法为引用传递(避免对象切片问题),然后在派生类中重写该方法,内部判断参数是否为DerivedResult类型:

  1. 修改基类BaseClass的run方法:
virtual void run(BaseResult& result) = 0;
  1. 在DerivedClassA中正确重写run方法:
void run(BaseResult& result) override {
    // 使用dynamic_cast判断参数是否为DerivedResult类型
    if (DerivedResult* derived_result = dynamic_cast<DerivedResult*>(&result)) {
        // 在这里编写处理DerivedResult的逻辑
        std::cout << "处理DerivedResult" << std::endl;
    } else {
        // 可选:处理其他BaseResult派生类的情况,或抛出异常
    }
}

如果必须保留值传递(不推荐,会导致切片),可以这样重写:

void run(BaseResult result) override {
    // 由于切片,这里无法直接获取DerivedResult的额外成员,仅能判断类型
    if (typeid(result) == typeid(DerivedResult)) {
        // 处理逻辑(但无法访问DerivedResult的专属成员)
    }
}

方案二:调整基类为模板类(牺牲多态性)

如果你的场景不需要多态,可以将BaseClass改为模板类,指定结果类型:

template<typename ResultType>
class BaseClass {
public:
    virtual ~BaseClass() = default;
    virtual void impl(int test) = 0;
    virtual void run(ResultType result) = 0;
};

class DerivedClassA : public BaseClass<DerivedResult> {
public:
    // ... 其他代码 ...
    void run(DerivedResult result) override {
        // 直接处理DerivedResult
    }
};

注意:这种方式下,std::vector<std::shared_ptr<BaseClass>>无法再容纳不同结果类型的派生类,因为模板实例化后是不同的类型。

额外说明

派生类中的static void run()与基类的虚函数无关,不会影响抽象类的判断,但如果不需要可以移除,避免混淆。


内容的提问来源于stack exchange,提问作者raaj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 23:10:53