c++ - 在 C++ std::<vector> 容器中存储多种类型结构的模式

标签 c++ design-patterns

我有一个表示火车的数据结构,它可以由多种类型的汽车组成,例如火车引擎、运粮车、客车等:

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/

相关文章:

scala - 在 Scala 中编写 Builder 模式,同时隐藏案例类直接访问

c++ - 避免舍入错误(特别是 float )c++

java - 使用 JAXB 注释应用复合模式的最佳方法?

java - 关于代理平等的查询

android - 使用编译的 lua 脚本的 Cocos2d-x 在 Android 上不起作用

sql - 获取 1 :n database relations into code 的最佳实践

java - 就像我们搭建乐高一样聚合 JSP 页面的最佳方式

c++ - 调用删除时出现段错误

c++ - 用于与 arduino 进行串行通信的 struct termios 设置

c++ - 存储在 std::map/std::set 中与存储所有数据后对 vector 进行排序