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

C++中基类的动态类型转换问题(兼容C++14)

问题分析与解决方案

原代码存在三个核心问题,导致无法实现预期的多态输出:

  1. 对象切片:函数s返回A类型对象,当返回子类B/C时,会被切割成基类A的实例,丢失子类特有的信息和行为。
  2. 无多态支持:基类A没有定义任何虚函数,无法通过基类指针/引用触发子类的operator<<重载。
  3. 非法解引用:s返回的是A对象而非指针,*(s(0))属于语法错误,编译无法通过。

以下是兼容C++14标准的修改方案:

修改后的完整代码

#include <iostream>
#include <memory>
#include <string>
using namespace std;

class A {
public:
    // 虚析构:确保子类对象通过基类指针销毁时能正确调用子类析构
    virtual ~A() = default;
    // 纯虚打印函数:定义多态接口
    virtual void print(ostream& out) const = 0;
};

// 全局operator<<,调用基类的虚print函数实现多态输出
ostream& operator<<(ostream& out, const A& obj) {
    obj.print(out);
    return out;
}

class B : public A {
public:
    explicit B(string s) {}

    // 实现基类的纯虚print函数
    void print(ostream& out) const override {
        out << "b";
    }
};

class C : public A {
public:
    explicit C(int i) {}

    // 实现基类的纯虚print函数
    void print(ostream& out) const override {
        out << "c";
    }
};

// 返回unique_ptr<A>,避免对象切片,同时自动管理内存(C++14支持)
unique_ptr<A> s(int i) {
    if (i == 0) {
        return make_unique<B>("hello world");
    } else {
        return make_unique<C>(12);
    }
}

int main() {
    // 解引用unique_ptr获取基类引用,触发多态输出
    cout << *(s(0)) << endl; // 输出"b"
    cout << *(s(1)) << endl; // 输出"c"
    return 0;
}

修改细节说明

  • 基类添加虚函数:为A添加虚析构和纯虚print函数,开启多态支持。虚析构是必须的,否则通过基类指针销毁子类对象会导致未定义行为。
  • 替换返回值类型:将s的返回值从A改为unique_ptr<A>,避免对象切片,同时利用智能指针自动管理内存,无需手动释放(C++14的make_unique是标准库函数,安全高效)。
  • 调整输出逻辑:将子类的friend operator<<改为实现基类的print虚函数,全局operator<<统一调用基类的print,确保通过基类引用能触发子类的输出逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 23:52:31