如何使用dynamic_cast筛选用户指定类型的对象?
问题描述
需要实现一个方法,将特定类型的Car子类对象筛选出来存入新列表,但dynamic_cast无法直接接收std::string作为类型参数,求可行的优化方案。原示例代码如下:
std::list<Car*> GetCarsOfType(std::string type) { std::list<Car*> carsOfType; for (int i = 0; i < cars.size(); ++i) { if (dynamic_cast<type> cars[i]) // 此处无法直接实现,需要替代方案 { carsOfType.push_back(cars[i]); } } return carsOfType; }
方案一:利用RTTI与typeid匹配
借助C++的RTTI(运行时类型信息)特性,用typeid获取对象的实际类型,再与目标类型名匹配。注意typeid的返回格式因编译器而异,需要提前确认或做映射处理。
示例代码:
#include <typeinfo> #include <list> class Car { public: virtual ~Car() = default; }; class Sedan : public Car {}; class SUV : public Car {}; std::list<Car*> GetCarsOfType(std::list<Car*>& cars, const std::string& type) { std::list<Car*> result; for (Car* car : cars) { if (!car) continue; // 不同编译器返回的typeid名称格式不同,比如GCC返回"Sedan",MSVC可能返回"class Sedan" if (typeid(*car).name() == type) { result.push_back(car); } } return result; }
方案二:基类添加自定义类型标签(推荐)
在Car基类中定义纯虚方法返回自定义类型标识(枚举或字符串),子类重写该方法返回对应标识。这种方式不依赖RTTI,兼容性和可控性更强。
示例代码:
#include <list> #include <string> #include <stdexcept> enum class CarType { Sedan, SUV, Truck }; class Car { public: virtual ~Car() = default; virtual CarType GetCarType() const = 0; }; class Sedan : public Car { public: CarType GetCarType() const override { return CarType::Sedan; } }; class SUV : public Car { public: CarType GetCarType() const override { return CarType::SUV; } }; // 把输入字符串转为枚举类型 CarType StringToCarType(const std::string& type) { if (type == "Sedan") return CarType::Sedan; if (type == "SUV") return CarType::SUV; throw std::invalid_argument("未知车型"); } std::list<Car*> GetCarsOfType(std::list<Car*>& cars, const std::string& type) { std::list<Car*> result; CarType targetType = StringToCarType(type); for (Car* car : cars) { if (car && car->GetCarType() == targetType) { result.push_back(car); } } return result; }
方案三:动态类型注册(进阶)
如果需要支持动态扩展子类,可以实现一个全局类型映射表,将类型名与对应的dynamic_cast判断逻辑绑定,新增子类时只需注册即可。
示例代码:
#include <list> #include <string> #include <unordered_map> #include <functional> class Car { public: virtual ~Car() = default; }; class Sedan : public Car {}; class SUV : public Car {}; // 存储类型名到判断函数的映射 std::unordered_map<std::string, std::function<bool(Car*)>> carTypeCheckers; // 注册类型判断逻辑 template<typename T> void RegisterCarType(const std::string& typeName) { carTypeCheckers[typeName] = [](Car* car) { return dynamic_cast<T*>(car) != nullptr; }; } // 初始化注册现有车型 void InitCarTypes() { RegisterCarType<Sedan>("Sedan"); RegisterCarType<SUV>("SUV"); } std::list<Car*> GetCarsOfType(std::list<Car*>& cars, const std::string& type) { std::list<Car*> result; auto checkerIt = carTypeCheckers.find(type); if (checkerIt == carTypeCheckers.end()) { return result; // 或抛出异常提示未知类型 } const auto& typeChecker = checkerIt->second; for (Car* car : cars) { if (car && typeChecker(car)) { result.push_back(car); } } return result; }
内容的提问来源于stack exchange,提问作者Fox1942
相关产品推荐
相关产品推荐

