让我们看看示例类。基类是ITransport,传输类接口:
class ITransport {
public:
virtual void move(const Path& p) = 0;
virtual double estimateTime(const Path& path) = 0;
/*Some more methods.*/
};执行情况:
class Transport : public ITransport {
public:
virtual void move(const Path& p) override {
currPoint_ = p.lastPoint();
}
/*Some more methods.*/
private:
Point currPoint_;
};让我们想象一下,我们想要创建一个自移动传输类:
template <typename EnergySource>
class SelfMovingTransport : public Transport {
/*Some special methods for self moving transport.*/
};汽车是自动运输的最简单的例子:
template <typename EnergySource>
class Car : public SelfMovingTransport <EnergySource> {
public:
virtual void visitCarService() = 0;
/*Some more methods with logic for cars.*/
};还需要用内燃机制造汽车..。
class ICECar : public Car<Petrol> {
public:
virtual void move(const Path& p) override {
Transport::move(p);
/*Some special methods for ICECar.*/
}
virtual void visitCarService() override {
/*Visit closest ICECar service.*/
}
/*Some special methods for ICECar.*/
private:
Petrol::Amount petrol_;
};..。还有一辆电动汽车。
class ElectricCar : public Car<Electriсity> {
public:
virtual void move(const Path& p) override {
Transport::move(p);
/*Some special methods for ElectricCar.*/
}
virtual void visitCarService() override {
/*Visit closest ElectricCar service.*/
}
/*Some special methods for ElectricCar.*/
private:
Electricity::Amount charge_;
};例如,这个逻辑的延续可以是添加列车类等等:
template <typename EnergySource>
class Train : public SelfMovingTransport<EnergySource> {
/*Not interesting.*/
};我使用c++17压缩器(MS)。不要少,不要多。
我想要创建一个指向不同类型汽车的指针的数组(或std::vector<Car*>),并为它们调用一些常用的方法。例如,有一种简单的方法将它们全部发送到服务(请参阅Car::visitCarServeice())。
我试过树的想法:
ISelfMovingTransport和ICar类ISelfMovingTransport :公共虚拟ITransport { /*All相同.*/ };类ICar :公共虚拟ISelfMovingTransport { /*All相同.*/ }; 将
Transprot更改为: 类传输:公共虚拟ITransport { /*。*/ } 将SelfMovingTransport更改为: 模板类SelfMovingTransport :公共ISelfMovingTransport,公共传输{}; 将Car更改为: 模板类Car:公共ICar,公共SelfMovingTransport { /*All相同*/ }; 最终解决方案不起作用,因为static_cast不能用于将指针转换到实际派生的类指针(请参阅pastebin 链接.)。示例代码无法编译(错误:不能从指针转换为基类“ISelfMovingTransport”到派生类“ElectricCar”,因为基是虚拟的)。当我想使用作为指向ElectricCar的指针访问的Car进行操作时,我需要dynamic_cast<ElectricCar*>(carPtr),carPtr位于Car*的位置。但是dynamic_cast是不允许的,RTTI被关闭了。
std::vector<Transport*>和强制转换对象转换为Car。它起了作用,但我不喜欢这个解决方案,因为很难检查是否一切都是正确的。std::variant<ICECar, ElectricCar>和std::visit。(std::visit([](auto& car) -> void { car.visitCarServeice(); }, carV))。(现在用此方法实现)。在这个例子中(它代表了实际项目中的一个问题),我不想改变逻辑(特别是从Transport级别到Car级别的类)。
在没有RTTI和dynamic_cast的情况下,是否有一种通用的方法来完成所需的事情?
在这种情况下,std::variant 'OK‘(假设car类的大小和/或内存不重要)吗?
问个问题,因为我不知道怎么用谷歌搜索。
所有的例子都是表示(模拟,等等)真实项目中的情况。我要求你们想象能源类型作为参数是真正需要的,而不是考虑复杂的问题(混合动力汽车等等)。
在实际的项目中,我需要一个“汽车”的唯一对象作为其他类的一个领域。
发布于 2021-08-04 02:29:26
我相信这解决了你的问题,但很难说。它删除了代码中的一些细节,但演示了该技术。它使用std::variant和std::visit。
#include <iostream>
#include <memory>
#include <variant>
class Car {
public:
Car( ) = default;
};
class ICECar : public Car {
public:
ICECar( ) {
}
void visitCarService( ) {
std::cout << "ICE visitCarService\n";
}
};
class ECar : public Car {
public:
ECar( ) {
}
void visitCarService( ) {
std::cout << "E visitCarService\n";
}
};
using car_variant = std::variant<
std::shared_ptr<ICECar>,
std::shared_ptr<ECar>>;
template <size_t C>
void visitCarService(std::array<car_variant, C>& cars) {
for (auto& c : cars) {
std::visit(
[](auto&& arg) {
arg->visitCarService( );
},
c);
}
}
int main(int argc, char** argv) {
ICECar ice_car { };
ECar e_car { };
std::array<car_variant, 2> cars {
std::make_shared<ICECar>(ice_car),
std::make_shared<ECar>(e_car)
};
visitCarService(cars);
return 0;
}这是用GCC 11编写的,用std=c++17和-pedantic集编写。据推测,它应该在这里女士下编译,这是一个在线运行的版本。
发布于 2021-07-30 00:17:34
我想创建一系列不同类型的汽车。
你不能。数组在C++中是同构的。所有元素都有相同的类型。
对Car使用
std::vector<Transport*>和cast对象
如果向量元素只指向cars,那么使用指向ICar的指针似乎更有意义。此外,如果向量应该拥有指定的对象,那么您应该使用智能指针。你需要把析构函数变成虚拟的。
在没有RTTI和dynamic_cast的情况下,是否有一种通用的方法来完成所需的事情?
通常是:虚拟函数。
在这种情况下,变体'OK‘是:
如果变体的数量是一个小常数的话,它可以是。相反,继承层次结构允许添加任意多个子类。
https://stackoverflow.com/questions/68583876
复制相似问题