C++如何将继承同一父类的不同子类对象存储到同一个数组中
问题原因分析
- 你将子类实例地址赋值给父类指针
Vehicle*后,父类指针的静态类型为Vehicle,仅能访问Vehicle类中定义的成员,子类独有的currentMileage、motorType等成员无法直接访问,所以触发编译报错 - 额外问题:你声明的
vehicleID和man是Vehicle的私有成员,子类/外部无法直接访问;同时用%c打印string类型的man属于格式符不匹配,运行会出错
可行解决方案
方案1:使用虚函数实现多态(最推荐,符合面向对象设计)
在父类中定义虚接口,不同子类各自实现对应逻辑,不需要暴露子类独有成员,也不需要强制类型转换:
class Vehicle { private: string vehicleID; string man; public: Vehicle(string, string); Vehicle(); // 新增get方法访问私有成员 string getVehicleID() const { return vehicleID; } string getMan() const { return man; } // 定义虚接口,子类各自实现 virtual void printInfo() const { printf("车辆ID:%s,厂商:%s\n", getVehicleID().c_str(), getMan().c_str()); } virtual ~Vehicle(); }; class Bus: public Vehicle { public: int currentMileage; Bus(string, string, int); Bus(); // 重写虚接口 void printInfo() const override { printf("巴士:ID %s,厂商 %s,当前里程 %d\n", getVehicleID().c_str(), getMan().c_str(), currentMileage); } virtual ~Bus(); }; class Train: public Vehicle { public: char motorType; Train(string, string, char); Train(); void printInfo() const override { printf("火车:ID %s,厂商 %s,动力类型 %c\n", getVehicleID().c_str(), getMan().c_str(), motorType); } virtual~Train(); };
使用时直接调用虚函数即可:
Vehicle* arrVehicle[2]; arrVehicle[0] = new Bus("001", "巴士厂商", 12000); arrVehicle[1] = new Train("002", "火车厂商", 'E'); for(int i=0; i<2; i++) { arrVehicle[i]->printInfo(); // 自动调用对应子类的实现 } // 记得释放内存避免泄漏 for(int i=0; i<2; i++) { delete arrVehicle[i]; }
方案2:向下转型访问子类独有成员
如果确实需要单独访问子类独有的成员,可以用dynamic_cast做安全类型转换,转换前会做类型校验,转换失败返回空指针:
Vehicle* arrVehicle[2]; arrVehicle[0] = new Bus("001", "巴士厂商", 12000); arrVehicle[1] = new Train("002", "火车厂商", 'E'); // 尝试转换为Bus类型 Bus* busPtr = dynamic_cast<Bus*>(arrVehicle[0]); if(busPtr != nullptr) { printf("%i\n", busPtr->currentMileage); printf("%s\n", busPtr->getMan().c_str()); } // 尝试转换为Train类型 Train* trainPtr = dynamic_cast<Train*>(arrVehicle[1]); if(trainPtr != nullptr) { printf("%c\n", trainPtr->motorType); }
注意:使用
dynamic_cast需要开启编译器的RTTI(运行时类型信息)支持,大部分编译器默认开启。
方案3:C++17及以上版本使用std::variant存储
不需要继承关系也可以存储不同类型的对象,用std::visit访问:
#include <variant> #include <vector> // 定义variant类型,可存储三种子类对象 using VehicleVariant = std::variant<Bus, Train, Helicopter>; std::vector<VehicleVariant> arrVehicle; arrVehicle.emplace_back(Bus("001", "巴士厂商", 12000)); arrVehicle.emplace_back(Train("002", "火车厂商", 'E')); // 访问时用visit for(auto& v : arrVehicle) { std::visit([](auto&& vehicle) { printf("厂商:%s\n", vehicle.getMan().c_str()); // 判断类型访问独有成员 if constexpr (std::is_same_v<std::decay_t<decltype(vehicle)>, Bus>) { printf("里程:%d\n", vehicle.currentMileage); } else if constexpr (std::is_same_v<std::decay_t<decltype(vehicle)>, Train>) { printf("动力类型:%c\n", vehicle.motorType); } }, v); }
内容的提问来源于stack exchange,提问作者User Userus
相关产品推荐
相关产品推荐

