C 映射类成号码
c++ Mapping class to number
i最近从C 开发开始。我遇到了一个无法解决问题的问题,因为我不知道是否可能。
我想在数字和类之间创建一个映射,这些映射是从抽象类得出的。
本质上,我想做的就是创建一种工厂方法,该方法可以基于与该类关联的给定编号创建类的新实例。
我知道我可以做以下...
Vehicle *Vehicle::from_type(byte type)
{
switch(type)
{
case 0x00: return new Bicyle();
case 0x01: return new Car();
...
case 0x10: return new Truck();
}
return null;
}
...,但我不想让它保持干燥。
在某种程度上,人们可以按照此操作来做些事情:
// I know this is incorrect syntax
const map<byte, class extends Vehicle> VEHICLE_MAPPING = {{0x00, Bicyle}, {0x01, Car}, ..., {0x10, Truck}};
Vehicle *Vehicle::from_type(byte type)
{
return new VEHICLE_MAPPING[type]();
}
我可以看到您的方法如何与std::map<uint8_t, std::unique_ptr<Vehicle>>
的使用一起使用,但是存在问题 - 您将无法使用initializer_list
初始化该映射,因为它 copies copies 元素,众所周知,std::unique_ptr
无法复制。您将必须创建一个init()
函数才能初始化将使用与Vehicle *Vehicle::from_type(byte type)
相似的逻辑的地图,这简直是毫无意义的。
此外,我不同意您的第一个解决方案违反了干燥。实际上,这是正确的,从某种意义上说,您不会被迫在代码中其他位置使用switch
或if
S。我一定会坚持下去。
最终注释 - 您可以使用std::map<uint8_t, std::shared_ptr<Vehicle>>
代替std::map<uint8_t, std::unique_ptr<Vehicle>>
并使用initializer_list
初始化,因为std::shared_ptr
可以复制,但我不建议这样做,因为它是错误的表示shared_ptr
的用法。如果您以某种方式被迫这样做,这里是一个例子:
class Base{ public: virtual ~Base() = default; };
class Derived1 : public Base{};
class Derived2 : public Base{};
class derived_factory{
private:
derived_factory();
static inline std::map<uint8_t, std::shared_ptr<Base>> base_map = {
{0x00, std::make_shared<Derived1>()},
{0x01, std::make_shared<Derived2>()}
};
public:
static std::unique_ptr<Base> from_type(uint8_t type)
{
return std::make_unique<Base>(*base_map[type]);
}
};
int main()
{
auto ptr = derived_factory::from_type(0x00);
// ptr is of a type std::unique_ptr<Base> and points to Derived1 object
}
其他应该是最终使用此解决方案的问题是它的速度很慢。它在地图中构造对象,除了将它们保留为"模板"复制示例之外,它们没有任何作用。
如果它们都是从基类得出的,则可以使用工厂模式,例如,从loki的实现中使用(请参阅现代C 设计有关详细信息,虽然那本书是pre-c 11)。
以下会创建一些混凝土车辆,并将其放入向量,然后在其中调用drive()
方法:
#include <iostream>
#include <memory>
#include <vector>
#include "factory.h"
struct Vehicle
{
virtual ~Vehicle() = default;
virtual void drive() = 0;
};
struct Car : Vehicle
{
static constexpr auto ID = 1;
void drive() override { std::cout << "Carn"; }
};
struct Truck : Vehicle
{
static constexpr auto ID = 2;
void drive() override { std::cout << "Truckn"; }
};
// Create the factory object
auto g_factory = MyUtil::Factory<std::unique_ptr<Vehicle>, int>{};
void RegisterTypesWithFactory()
{
// We pass in creator functions for each type. Note that these
// could be lambdas or some other freestanding function and they
// could accept parameters.
g_factory.Register( Car::ID, &std::make_unique<Car> );
g_factory.Register( Truck::ID, &std::make_unique<Truck> );
}
int main()
{
// Configure the factory
// Note: Registration can be done any time, e.g., later based on input
// from a file. I do them all at once here for convenience of illustration.
RegisterTypesWithFactory();
// Create some objects with the factory
auto vehicles = std::vector<std::unique_ptr<Vehicle>>{};
vehicles.emplace_back( g_factory.Create( Car::ID ) );
vehicles.emplace_back( g_factory.Create( Truck::ID ) );
// Do something with the objects
for( const auto& v : vehicles )
{
v->drive();
}
}
打印:
Car
Truck
看到它在 wandbox 中实时运行。
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 将函数类成员映射到类本身内部
- 如何在 C# 中映射双 C 结构指针?
- 如何在C++中使用结构生成映射
- 使用std::函数映射对象方法
- 如何加载(或映射)文件部分的最大大小,但适合在Windows上的RAM
- C++映射分割错误(核心转储)
- 内联映射初始化的动态atexit析构函数崩溃
- 使用"std::unordereded_map"映射到"std::list"对象
- 如何从多映射中删除特定的重复项
- 在未初始化映射的情况下,将值插入到映射的映射中
- QT通过C++添加映射QML项目
- 在c++中访问int到类对象的映射时出错
- 在C++中搜索嵌套多映射值
- 错误处理.将系统错误代码映射到泛型
- C++匿名结构作为std::映射值
- 如何从存储在std::映射中的std::集中删除元素
- 递归无序映射
- C 映射类成号码