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

C++工厂函数问题排查与修正:如何让输出变为1 2 3?

问题分析与修复方案

先直接拆解你的代码里导致输出全为0的核心问题,再给出完整的修复方案:

1. 致命的对象切片问题

你在工厂函数里写的make_unique<Base>(A())这类代码,本质是用派生类对象去构造基类对象,这会触发C++的「对象切片」——派生类特有的数据和行为会被直接切掉,最终你拿到的永远是一个纯Base类型的对象,而非你期望的A/B/C派生类对象。这是所有输出都是0的核心原因。

2. Switch分支缺少break导致逻辑贯穿

你的switch语句里每个case后都没加break,比如当传入_A时,代码会依次执行_A、_B、_C的分支,最后都会走到base = make_unique<Base>(C())。不过因为已经有切片问题,这个bug暂时没影响最终输出,但必须修复。

3. 派生类未正确重写虚函数

基类的getType()是虚函数,但你的A/B/C类并没有重写它,只是各自定义了一个私有type成员。这意味着哪怕你拿到了真正的派生类对象,调用getType()还是会执行基类的版本,返回基类的_Base值。


修复后的完整代码

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

enum Type { _Base, _A, _B, _C };

class Base{
protected: 
    Type type = _Base;
public: 
    virtual Type getType(){ return type; }
    // 基类必须加虚析构,避免通过基类指针删除派生类时内存泄漏
    virtual ~Base() = default;
};

class A : public Base{
public: 
    A() { type = _A; }
    // 用override明确标记重写,让编译器帮你检查是否符合重写规则
    Type getType() override { return type; }
};

class B : public Base{
public: 
    B() { type = _B; }
    Type getType() override { return type; }
};

class C : public Base{
public: 
    C() { type = _C; }
    Type getType() override { return type; }
};

shared_ptr<Base> letterFactory(Type which){
    switch (which){
        case _A: 
            return make_shared<A>();
        case _B: 
            return make_shared<B>();
        case _C: 
            return make_shared<C>();
        default: 
            return make_shared<Base>();
    }
}

int main(){
    shared_ptr<Base> instanceOfA = letterFactory(_A);
    cout << instanceOfA->getType() << endl; // 输出1
    shared_ptr<Base> instanceOfB = letterFactory(_B);
    cout << instanceOfB->getType() << endl; // 输出2
    shared_ptr<Base> instanceOfC = letterFactory(_C);
    cout << instanceOfC->getType() << endl; // 输出3
    return 0;
};

关键修改说明

  • 解决对象切片:直接创建派生类的智能指针(make_shared<A>()),再返回给shared_ptr<Base>,利用C++多态特性,此时指针指向的是真正的派生类对象,不会被切片。
  • 修复分支逻辑:每个case直接返回对应智能指针,既避免了break的问题,也让代码更简洁。
  • 正确实现多态:
    • 把基类type改为protected,让派生类可以修改;
    • 派生类用override标记重写getType(),确保符合虚函数重写规则;
    • 给基类添加虚析构,避免内存泄漏。
  • 简化冗余代码:去掉了没必要的using Base::Base;,直接在派生类构造函数里设置type值。

这样修改后,程序就能输出1 2 3了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 09:12:46