如何让整数映射到 C++ 中的类定义
How to let an integer maps to a class definition in C++?
我有一些类:
class Base
{
public:
virtual void Something() = 0;
}
class A : public Base
{
public:
virtual void Something() { /*...*/ }
void SpecialActionForA();
}
class B : public Base
{
public:
virtual void Something() { /*...*/ }
void SpecialActionForB();
}
和一个数组:
Base* MyMembers[2];
MyMembers[0] = new A;
MyMembers[1] = new B;
我想做:
A* pointer_to_a = Get(0);
B* pointer_to_b = Get(1);
有什么好方法可以实现这个Get()
功能吗?
我的解决方案是:
template <typename T>
T* Get(int index)
{
return dynamic_cast<T*>(MyMembers[index]);
}
但首先是我必须写
A* pointer_to_a = Get<A>(0)
这需要额外的<A>
;
第二件事是,如果new
以某种方式搞砸了,例如:
MyMembers[0] = new B;
然后Get()
失败。
我想要的是一种自动机制,可以将索引 0 映射到 A。
额外详情:实际上,我从Base
派生了80
不同的类(它们是我的用户界面),
我需要的是让真正的类(真正的 UI)来做事。
我需要使用的功能是上述SpecialActionForA()
...等。
也使用该Something()
,但处于这些 UI 的初始化阶段,或由 UI 管理器系统管理的内容。
不能执行unknown* Get(int)
,因为它需要两个或多个具有相同名称但仅在返回值上不同的函数。C++明确禁止这样做。
您可以获得的最接近的函数是:
template <typename T> T* Get() {
static T* instance = new T;
return instance;
}
因此,您将能够将其用作:
A *a = Get<A>();
B *b = Get<B>();
通过查找参数列表来重载函数。仅通过判断返回类型无法了解您想要什么样的值。因此,编译器强制您提供额外的详细信息来实例化模板。因此,您的选择是:
Base *Get(int N) {
return MyMembers[N];
}
或
A *GetA(int N) {
return MyMembers[N];
}
B *GetB(int N) {
return MyMembers[N];
}
或
template <typename T> void Get(int N, T *&item) {
item = (T*)MyMembers[N];
}
A* pointer_to_a;
B* pointer_to_b;
Get(0, pointer_to_a);
Get(1, pointer_to_b);
或您自己的
template <typename T>
T* Get(int index)
{
return dynamic_cast<T*>(MyMembers[index]);
}
在不知道您的使用场景的情况下,很难提供有用的答案,但我实际上确实相信您想要的是类型匹配。所以你要做的是将变量作为 Base 指针传递,直到我你实际上需要知道具体的底层类型,此时你对基指针的基础类型进行匹配。这与混合了 lambda 的开关语句非常相似,我将尝试提供一个示例。
...
Base* ptr = some_argument;
// Here we need the underlying type, so we'll do a match
Match(ptr)
{
Case(A* a)
{
// this is invoked if ptr happened to hold an A, now do something A specific.
}
Case(B* b)
{
// this is invoked if ptr happened to hold a B, now do something B specific
}
Otherwise()
{
// this is invoked whenever none of the above are
}
}
EndMatch;
...
这是通常解决方案的替代方法,通常解决方案是基类中的虚拟指针和重写。请注意,类型匹配通常用于函数式语言。对于C++来说,有一个切肉刀解决方案可以实现这一目标,由Bjarne Stroustrup的博士生之一Yuriy Solodkyy提供。
简短的介绍性论文可以在这里找到;
https://parasol.tamu.edu/~yuriys/papers/OPM13EA.pdf
有关更多信息,请查看提交给 ISO 委员会的 hvis 论文;用于C++的开放式高效型开关,由Stroustup,Dos Reis和Solodkyy提供
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3449.pdf
有关这些论文背后的源代码,请访问Yuriys主页;
https://parasol.tamu.edu/~yuriys/pm/
如果你拥有的类数是真正封闭的,那么考虑使用闭合代数数据类型,就像boost::variant
一样。与不受限制的开放代数数据类型相比,这些数据类型具有一些优点,因为编译器通常可以确保穷举匹配,并且封闭性质允许更优化的模式匹配实现,尽管以灵活性为代价。
另请注意,boost::variant
在 C++03 上运行良好!
但是,请考虑是否真的需要模式匹配或多态调度。这两种方法都有优点和缺点,模式匹配方法的主要优点是不需要更改类,并且避免使用超特定的虚拟方法污染基类,这些方法只能在一个位置调用。
- 在提升multi_index容器中,是否定义了"default index"?
- #定义c-预处理器常量..我做错了什么
- 用C++中的一个变量定义一个常量
- 部分定义/别名模板模板参数
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- #为""定义宏;静态";针对不同的上下文
- 如何确保C++函数在定义之前声明(如override关键字)
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 当类在C++中定义时,有什么方法可以"register"类吗?
- 在命名空间中定义函数还是限定函数
- 此代码是否违反一个定义规则
- 编译C++时未定义的引用
- 不同翻译单元中不可重载的非内联函数定义
- 为什么在定义函数之前先声明它
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 在类定义之后定义一个私有方法
- 使用用户定义函数的字符串反转
- 用户定义函数中的指针和输入
- vscode g++链路故障:体系结构x86_64的未定义符号
- 如何定义一个纯抽象基类