如何存储不同类对象且不丢失信息?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
相关产品推荐
相关产品推荐

