使用多态性创建"类型数组"
Using polymorphism to create 'array of types'
我需要能够基于ID检索类型。
为了实现这一点,我打算为类型创建一个基类,它将所有函数声明为纯虚拟函数。
class Base
{
public:
virtual int function1() = 0;
virtual int function2() = 0;
};
然后,我创建派生类,实例化这些类,并将指向实例的指针存储在基指针的std::unordered_map
中。
std::unordered_map<int, Base*> types;
std::unordered_map
的每个元素将指向不同的派生类类型(即没有重复)。
然后,我可以通过从std::unordered_map
获取关联成员来检索我需要的类型。
Base* ptr = types[4];
// Use type...
int num = ptr->function1();
现在我知道这可以归结为意见,但这是对C++的可怕使用吗?有更干净的方法吗?
更新
我可以使用派生类的实例,而不是它们各自的ID,但我可能必须在堆上动态分配每个派生类(即使用new
),并且我将创建这些派生类的批,因此动态分配的开销可能会对性能产生不必要的影响。
现在我知道这可以归结为意见,但这是一个可怕的用途吗C++?有更干净的方法吗?
在示例代码中,我只能看到一件可以被称为可怕的事情,那就是缺乏抽象。然而,这个概念本身是完全可以的
这里有两个机制:一个多态基类,一个映射,它为您提供了一个基于某种不透明id的对象实例——在本例中是int
,但它也可能是例如std::string
,什么都不会真正改变。
基类是最经典的,根据标准良好实践,它还应该有一个虚拟析构函数。除此之外,那里没有什么可看的。
从概念上讲,这个映射就是所谓的"单例工厂"。这是一个工厂,因为你调用了一个传递id的方法,然后得到了一个与该id对应的对象,唯一的区别是每次调用具有相同id的方法时都会得到相同的实例。从高级角度来看,这对客户端来说根本不感兴趣。客户只关心,例如,每次他们通过4
时,他们都会得到一个Widget*
。当您查看客户端代码时,工厂如何获取该实例以返回指针并不重要。所以这里也没有什么特别之处,至少在设计层面上是这样。
扩展这条思路会导致可能的缺陷:客户端不需要知道工厂是如何满足请求的,但公开实现(直接访问std::unordered_map
)可以让客户端知道一切,还可以让他们对工厂做一些可能不允许他们做的事情(如注销类型)。通过创建一个新的类来封装映射并公开一个公共接口,可以很容易地解决这个问题,您可以根据需要自由设计该接口。
这是对C++的可怕使用吗?——是的,也许更好的表达方式是"不使用多态性",即你没有(正确地)使用多态性。
您不需要像编译器通过多态性为您做的那样首先跟踪类型:
1) 只需在基类中声明方法virtual(您已经这样做了)。
2) 覆盖子类中的方法。
类似:
class Base {
public:
virtual int myId(){ return 0; }
};
class Child1: public Base {
public:
int myId() { return 1; }
};
- C++默认情况下,指针类型数组的元素是否保证初始化为 nullptr?
- 类型数组?
- 如何在使用 make_unique<T[]>() 制作的模板类型数组上使用 std::fill?
- 将基本类型数组中的内存重新用于不同(但仍然是基本)类型的数组合法吗
- 在C++中返回基元类型数组(Java比较)
- 如何返回 QVariant 类型数组
- 如何在本机 c++ jni 中实现 java 类型数组
- 模板类型数组的模板类型数组
- 如何确定未知类型数组的索引是否为空
- 复杂类型数组的静态初始化
- 访问基类型数组成员(Int-to-type习惯用法)
- 如何将 char 类型数组传递给函数并将第一个字符数组复制到第二个图表数组并使用 c++ 进行比较
- 如何在C 中制作结构类型数组
- 如何创建结构类型数组的地图对象
- C++类类型数组
- C++中的Matlab类型数组
- 节点C++插件 - 当类型数组(Float32Array)作为参数传递时,如何访问它?
- 如何将二维字符类型数组逐行保存到 c 中的.txt文件中
- C++:用户定义的类型数组出错
- 在双精度类型数组中使用 memset()