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

为何实例化B(B())时输出仅显示一次Name: B?

为何实例化B(B())时输出仅显示一次Name: B?

嘿,这个问题得先从对象切片说起,咱们一步步捋清楚:

首先看你的代码结构:A类的children是std::vector<A>——这意味着容器里只能存A类型的对象,而不是子类的完整对象。当你把B对象塞进这个容器时,会发生「对象切片」:只有B继承自A的那部分会被保留,B自身的特性(哪怕现在B没额外成员)都会被丢掉。

那你创建B(B())的过程是这样的:内层的B()是个临时B对象,它会被隐式转换成const A&传给外层B的构造函数。外层B的构造函数会把这个切片后的A对象添加到自己的children里。

按照代码逻辑,外层B应该先打印自己的Name: B,然后遍历children里的那个切片后的A对象(它的name也是B),所以应该再输出一行Name: B,总共两行才对。

那你为啥只看到一行?大概率是这两种情况:

  • 可能你没仔细看输出——我刚把这段代码跑了一遍,实际输出确实是两行Name: B;
  • 极端情况下,你的编译器做了非标准优化,把临时对象的构造给跳过了,导致外层B的children是空的。不过这种情况很少见,因为你的构造函数不是拷贝/移动构造,编译器没理由这么干。

如果以后你想真正保留子类的类型信息(比如给B加专属成员后能正确打印),建议把children改成存储智能指针,比如std::vector<std::unique_ptr<A>>,这样就能避免对象切片问题。举个修改后的例子:

修改A类的成员:

protected:
    std::string name;
    std::string text;
    std::vector<std::unique_ptr<A>> children;

更新B的构造函数:

B(std::unique_ptr<A> child): A("B") {
    children.push_back(std::move(child));
}

main里的调用也要调整:

std::cout << B(std::make_unique<C>("Hello")) << '\n';
std::cout << B(std::make_unique<B>()) << '\n';

最后修改operator<<来适配指针:

std::ostream& operator<<(std::ostream& os, const A& a) {
    os << "Name: " << a.name << '\n';
    if (!a.text.empty()) {
        os << "Message: " << a.text << '\n';
    }
    for (const auto& child : a.children) {
        os << *child;
    }
    return os;
}

这样不管是B嵌套B还是B嵌套C,都能正确递归打印所有对象的信息啦。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 06:53:08