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

C++中如何让类接受其属性类的子类作为参数?

解决类接受其父类子类作为属性的问题

原代码的核心问题是对象切片:当按值传递子类对象给接受基类的函数时,仅会复制基类部分,丢失子类特有的成员数据,无法保留多态特性。

正确实现方案

要支持多态地存储子类对象,需通过指针或引用操作,推荐使用智能指针管理生命周期:

  1. 基类添加虚析构函数:确保通过基类指针销毁子类对象时能正确调用子类析构函数,避免未定义行为。
  2. 用智能指针存储属性:在B中使用std::unique_ptr<A>替代A的实例,保留子类对象的完整信息。
  3. 优化构造函数:提供直接接受智能指针的构造函数,或添加模板构造函数简化子类对象的传入流程。

修正后的代码

#include <memory>
#include <iostream>

class A {
public:
    virtual ~A() = default; // 必须的虚析构函数
    virtual void show() const = 0; // 纯虚函数,让A成为抽象类(可选但推荐)
};

class B : public A {
    std::unique_ptr<A> a;

public:
    // 直接接受unique_ptr<A>的构造函数
    explicit B(std::unique_ptr<A> ptr) : a(std::move(ptr)) {}

    // 模板构造函数:自动包装任意A的子类
    template <typename Derived, typename... Args>
    explicit B(Args&&... args) : a(std::make_unique<Derived>(std::forward<Args>(args)...)) {}

    void show() const override {
        a->show(); // 调用子类的show方法
    }
};

class C : public A {
    int i;

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

    void show() const override {
        std::cout << "C类实例,值为:" << i << std::endl;
    }
};

// 可以添加更多A的子类,比如D
class D : public A {
    std::string s;

public:
    explicit D(std::string s) : s(std::move(s)) {}

    void show() const override {
        std::cout << "D类实例,字符串为:" << s << std::endl;
    }
};

int main() {
    // 方式1:使用模板构造函数直接传入子类构造参数
    B b1(std::make_unique<C>(1));
    // 更简洁的方式(通过模板构造函数)
    B b2(2); // 自动创建C(2)并包装为unique_ptr<A>
    B b3("hello"); // 自动创建D("hello")

    // 演示多态行为
    b1.show(); // 输出:C类实例,值为:1
    b2.show(); // 输出:C类实例,值为:2
    b3.show(); // 输出:D类实例,字符串为:hello

    return 0;
}

关键说明

  • 虚析构函数:基类A的虚析构函数是多态销毁的必要条件,否则会导致子类资源泄漏。
  • 智能指针:std::unique_ptr自动管理内存,无需手动释放,避免内存泄漏风险。
  • 模板构造函数:简化了B的实例化过程,无需手动创建智能指针,直接传入子类的构造参数即可。
  • public继承:原代码默认的private继承会导致子类无法被视为基类的公开派生类,改为public继承才能正确使用多态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 11:32:45