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

如何使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 03:00:52