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

如何存储不同类对象且不丢失信息?C++多态调用问题求助

问题原因:对象切片

当你将Town或Village对象直接存入vector<Place>时,会触发对象切片——容器仅会拷贝基类Place的部分,子类特有的属性和重写的PrintInfo实现都会被丢弃,因此调用时只会执行基类版本。

解决方案:使用指针/智能指针存储

要实现多态调用,容器需要存储基类的指针(或智能指针),而非直接存储基类对象。这样可以保留子类的完整信息,调用虚函数时会自动指向子类的实现。

步骤1:修正基类定义

确保基类包含虚析构函数(避免通过基类指针销毁子类对象时发生内存泄漏),并正确声明虚函数:

#include <iostream>
#include <vector>
#include <memory>
#include <string>

class Place {
public:
    // 虚析构函数:必须添加,确保子类析构被正确调用
    virtual ~Place() = default;

    // 虚方法,子类重写
    virtual void PrintInfo() const {
        std::cout << "Generic place" << std::endl;
    }
};

步骤2:子类实现(保持原有逻辑即可)

class Town : public Place {
private:
    std::string name;
    int population;
public:
    Town(std::string townName, int pop) : name(std::move(townName)), population(pop) {}

    // 使用override关键字确保正确重写(编译期检查)
    void PrintInfo() const override {
        std::cout << "Town: " << name << ", Population: " << population << std::endl;
    }
};

class Village : public Place {
private:
    std::string name;
    int houseCount;
public:
    Village(std::string villageName, int houses) : name(std::move(villageName)), houseCount(houses) {}

    void PrintInfo() const override {
        std::cout << "Village: " << name << ", House count: " << houseCount << std::endl;
    }
};

步骤3:使用智能指针存储(推荐,自动管理内存)

用std::unique_ptr或std::shared_ptr管理对象内存,无需手动释放:

int main() {
    std::vector<std::unique_ptr<Place>> places;

    // 直接构造子类对象并放入容器
    places.emplace_back(std::make_unique<Town>("Maplewood", 25000));
    places.emplace_back(std::make_unique<Village>("Willowbrook", 42));

    // 遍历调用,触发多态
    for (const auto& place : places) {
        place->PrintInfo();
    }

    // 无需手动释放内存,unique_ptr会自动清理
    return 0;
}

可选:使用原始指针(需手动管理内存)

如果必须使用原始指针,记得手动释放内存避免泄漏:

int main() {
    std::vector<Place*> places;

    places.push_back(new Town("Maplewood", 25000));
    places.push_back(new Village("Willowbrook", 42));

    for (const auto& place : places) {
        place->PrintInfo();
    }

    // 手动释放所有对象
    for (Place* p : places) {
        delete p;
    }
    places.clear();

    return 0;
}
关键注意点
  • 必须给基类添加虚析构函数,否则会导致子类资源泄漏
  • 使用override关键字可以在编译期检查是否正确重写了基类虚函数,避免拼写错误或签名不匹配
  • 优先使用智能指针(如std::unique_ptr),减少手动管理内存的错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 09:55:32