C ++:如何遍历类类型列表以进行类型标识验证和向下转换?
Posted
技术标签:
【中文标题】C ++:如何遍历类类型列表以进行类型标识验证和向下转换?【英文标题】:C++: How to iterate over a list of class types for typeid verification and downcasting? 【发布时间】:2021-10-15 01:37:02 【问题描述】:我想在执行时进行向下转换。
对于我阅读的内容,如果我想这样做,我需要将我的多态指针的typeid
与我的派生类的那些进行比较,然后以正确的类型进行转换。
另外,假设我有大量的派生类。
这意味着我必须写一个很长的switch
或if
的列表。
我想通过使用要检查的类列表来减少这项工作。
这可能看起来像:
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
using namespace std;
class BaseShapes
virtual int run() = 0;
;
class ClassRectangle : public BaseShapes
int run()
std::cout << "I am a Rectangle. " << std::endl;
return 0;
float get_length () return 12.4;;
float get_width() return 6.2;;
;
class ClassCircle : public BaseShapes
int run()
std::cout << "I am a Cricle. " << std::endl;
return 0;
float get_diameter() return 5.3;;
;
float function_only_for_Rectangle(ClassRectangle *rectangle)
// a function coming from a library that I cannot touch and that requires a derrived type.
// But for the example I do something dummy!
return rectangle->get_length()
;
auto downcast_function (auto *p)
enum ListOfTypes
ClassCircle,
ClassRectangle,
// and a lot more differents classes
;
for ( int fooInt = ClassCircle; fooInt < ClassRectangle; fooInt++ )
ListOfTypes fooItem = static_cast<ListOfTypes>(fooInt);
if (typeid(p) == typeid(fooItem))
auto pCasted =dynamic_cast<fooItem>(p);
return pCasted;
std::cout<< "downcast_function warning: no typeid is matching !" << std::endl;
return p;
;
int main(void)
// Beginning of main.
cout << "(Start)" << endl;
std::unique_ptr<BaseShapes> Shape1(new ClassRectangle());
auto p=Shape1.get();
//function_only_for_Rectangle(p); // not working since p is of type BaseShapes*
auto pbis=downcast_function(p); // should be of type ClassRectangle*
function_only_for_Rectangle(pbis);
// End of the main.
cout << "(End) " << endl;
return 0;
// EoF
那么我该如何写 downcast_function
呢?或者换句话说,我如何遍历类类型列表以进行typeid
比较和强制转换?
更多细节:
我同意在这个虚拟示例中,我可以简单地为每个派生类重写一个函数,这是处理多态性的更好方法。但我需要沮丧,这是一个来自更复杂问题的约束,其中它们是我不允许更改的东西。所以,这里的问题不是为什么沮丧,而是如何沮丧。
要提供有关我的约束的更多详细信息:
-
从基指针开始。
获取派生指针并将其提供给外部函数(此处称为
function_only_for_Rectangle
,因此我无法修改此函数)。
我不能做一个简单直接的dynamic_cast<ClassRectangle>(p)
,因为p
(或等效的Shape1
)的类型会在运行时改变。这意味着Shape1
可以“随机”拥有来自BaseShapes
的任何派生类型。所以我需要一些“自动”的东西,这就是为什么我正在考虑迭代所有派生类型并根据typeid
匹配向下转换(但我愿意接受更好的想法)。
如果需要,所有类都可以修改。
【问题讨论】:
你根本不会那样做,你只是遍历基础对象并调用它的虚函数,然后让编译器和运行时多态发挥它的“魔力”。 一个函数只能有 1 个返回类型,并且必须在编译时知道。使用auto
只是意味着你不需要自己指定类型是什么,编译器会为你做。
你为什么认为你需要做任何向下转换?你已经有了一个抽象接口。
@Someprogrammerdude 我编辑了我的问题,我认为这个编辑回复了你的 cmets:我不能做纯粹的多态性(我想做,但它不是来自我)。
@πάνταῥεῖ 我编辑了我的问题,并详细说明了我认为即使我有一个抽象接口也需要向下转换的原因。但我愿意接受任何想法来解决我的问题而不会沮丧。
【参考方案1】:
你说的是“多态”,但你想做的恰恰相反。
您可以实际使用它,而不是试图对抗多态性。如果所有子类都有自己的虚函数实现,那么调用者不需要关心对象的实际动态类型是什么。简而言之,这就是运行时多态性。
我想run
的命名只是为了示例。给它一个更好的名字,在基类中提供一个默认实现,在ClassRectangle
中实现特定的行为并让调用者调用它。无需投射。
class BaseShapes
virtual int do_something_rectangly() return 0;
~virtual BaseShapes() = default;
;
class ClassRectangle : public BaseShapes
int do_something_rectangly() override
std::cout << "I am a Rectangle. " << std::endl;
return 0;
;
class ClassCircle : public BaseShapes
// does not override do_something_rectangly()
;
int function_for_any_base_shape(BaseShapes& s)
return s.do_something_rectangly();
;
int main(void)
// Beginning of main.
cout << "(Start)" << endl;
std::unique_ptr<BaseShapes> Rec1(new ClassRectangle());
function_for_any_base_shape(*pbis);
cout << "(End) " << endl;
return 0;
关于您的编辑:
我不能做一个简单直接的 dynamic_cast(p) 因为 p 的类型(或等效的 Shape1)会在运行时改变。这意味着 Shape1 可以“随机”具有从 BaseShapes 派生的任何类型。 [...]
要么我完全误解了你写的内容,要么你误解了dynamic_cast
的工作原理。 dynamic_cast
已经检查了对象的动态类型是什么:
BaseShapes* b1 = new ClassCircle;
if(ClassRectangle* d = dynamic_cast<ClassRectangle*>(b1))
// cast is sucessfull
function_only_for_Rectangle(d);
else
// dynamic type of b1 is not ClassRectangle
要调用function_only_for_Rectangle
,您不需要能够转换为ClassBase
的所有子类型。您只需要将 dynamic_cast
指向指向 ClassRectangle
的指针并检查演员表是否成功。
【讨论】:
我编辑了我的问题。在一般情况下,我同意您的看法,这样做要好得多。但是我没有选择在这里沮丧以使来自“外部”的事物兼容。所以,从这个意义上说,你的答案并没有回答我的问题,即使它提供了更好的通用解决方案。 @R.N 我知道这是没有答案的。我打算为实际问题添加一些内容。穷人多态是enum subtype
和虚拟subtype getType()
或类似的东西
@R.N 但是,您的示例不是标题中问题的好示例(因为没有明显的需要强制转换)。请在问题中说明您可以更改哪些代码以及不能更改哪些代码
好的,我编辑了我的问题。我希望它更清楚,并且您有足够的思考解决方案。
@R.N 抱歉,但仍然不清楚为什么您认为您需要像 downcast_function
这样的东西。当您只想为矩形调用function_only_for_rectangle
时,可以使用dynamic_cast
以上是关于C ++:如何遍历类类型列表以进行类型标识验证和向下转换?的主要内容,如果未能解决你的问题,请参考以下文章
如何以交替顺序对两个不同对象列表的 XML 数组项进行排序?