我有一个表示火车的数据结构,它可以由多种类型的汽车组成,例如火车引擎、运粮车、客车等:
struct TrainCar {
// ...
Color color;
std::string registration_number;
unsigned long destination_id;
}
struct PowerCar : TrainCar {
// ...
const RealPowerCar &engine;
}
struct CargoCar : TrainCar {
// ...
const RealCargoCar &cargo;
bool full;
}
std::vector<TrainCar*> cars;
cars.push_back(new TrainCar(...));
cars.push_back(new TrainCar(...));
cars.push_back(new CargoCar(...));
cars.push_back(new CargoCar(...));
cars.push_back(new CargoCar(...));
一种算法将遍历火车中的车厢,并决定如何安排/调车每节车厢(是否将其保留在火车中、将其移动到火车中的另一点、将其从火车中移除)。此代码如下所示:
std::vector<TrainCar*>::iterator it = cars.begin();
for (; it != cars.end(); ++it) {
PowerCar *pc = dynamic_cast<PowerCar*>(*it);
CargoCar *cc = dynamic_cast<CargoCar*>(*it);
if (pc) {
// Apply some PowerCar routing specific logic here
if (start_of_train) {
// Add to some other data structure
}
else if (end_of_train && previous_car_is_also_a_powercar) {
// Add to some other data structure, remove from another one, check if something else...
}
else {
// ...
}
}
else if (cc) {
// Apply some CargoCar routing specific logic here
// Many business logic cases here
}
}
我不确定这种模式(使用 dynamic_casts 和 if 语句链)是否是处理不同类型的简单结构列表的最佳方式。 dynamic_cast 的使用似乎不正确。
一个选择是将路由逻辑移动到结构中(例如 (*it)->route(is_start_of_car, &some_other_data_structure...)),但是如果可能的话,我想将路由逻辑放在一起。
是否有更好的方法来遍历不同类型的简单结构(没有方法)?还是保留 dynamic_cast 方法?
最佳答案
对此的标准解决方案称为 double-dispatch .基本上,您首先将算法包装在为每种类型的汽车重载的单独函数中:
void routeCar(PowerCar *);
void routeCar(CargoCar *);
然后,在基类中为纯虚拟的 car 添加一个 route
方法,并在每个子类中实现:
struct TrainCar {
// ...
Color color;
std::string registration_number;
unsigned long destination_id;
virtual void route() = 0;
}
struct PowerCar : TrainCar {
// ...
const RealPowerCar &engine;
virtual void route() {
routeCar(this);
}
}
struct CargoCar : TrainCar {
// ...
const RealCargoCar &cargo;
bool full;
virtual void route() {
routeCar(this);
}
}
你的循环看起来像这样:
std::vector<TrainCar*>::iterator it = cars.begin();
for (; it != cars.end(); ++it) {
(*it)->route();
}
如果您想在运行时在不同的路由算法之间进行选择,您可以将 routeCar
函数包装在一个抽象基类中,并为此提供不同的实现。然后,您将该类的适当实例传递给 TrainCar::route
。
关于c++ - 在 C++ std::<vector> 容器中存储多种类型结构的模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7722359/