使用多态性创建"类型数组"

Using polymorphism to create 'array of types'

本文关键字:类型 数组 创建 多态性      更新时间:2023-10-16

我需要能够基于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; }
};