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类型:
- 修改基类
BaseClass的run方法:
virtual void run(BaseResult& result) = 0;
- 在
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
相关产品推荐
相关产品推荐

