C++:如何迭代 class 类型的列表以进行 typeid 验证和向下转换?
C++: How to iterate over a list of class types for typeid verification and downcasting?
我想在执行时进行向下转换。
根据我的阅读,如果我想这样做,我需要将多态指针的 typeid
与派生的 classes 进行比较,然后以正确的方式进行转换类型。
另外,假设我有大量派生的 classes。
这意味着我必须写一个长 switch
或 if
.
的列表
我想通过使用 classes 的列表来检查来减少这项工作。
这可能看起来像:
#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 derived 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
呢?或者换句话说,我如何遍历 class 类型的列表以进行 typeid
比较和转换?
更多详情:
我同意在这个虚拟示例中,我可以简单地为每个派生的 class 覆盖一个函数,这是处理多态性的更好方法。但我需要沮丧,这是一个来自更复杂问题的约束,在这些问题中,我不允许更改它们。所以,这里的问题不是为什么沮丧,而是如何沮丧。
要提供有关我的约束的更多详细信息:
从基指针开始。
得到一个派生指针,交给一个外部函数(这里叫function_only_for_Rectangle
,所以我不能修改这个函数)
我不能做一个简单直接的dynamic_cast<ClassRectangle>(p)
,因为p
(或等效的Shape1
)的类型会在运行时改变。这意味着 Shape1
可以“随机地”拥有来自 BaseShapes
的任何派生类型。所以我需要一些“自动”的东西,这就是为什么我考虑迭代所有派生类型并根据 typeid
匹配进行向下转换(但我愿意接受更好的想法)。
如果需要,所有 classes 都可以修改。
你说“多态”,但你想做的恰恰相反
您可以实际使用它,而不是试图反对多态性。如果所有 subclasses 都有自己的虚函数实现,那么调用者不需要关心对象的实际动态类型是什么。简而言之就是运行时多态性。
我想 run
的命名只是为了举例。给它一个更好的名字,在基础 class 中提供默认实现,在 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;
}
关于您的编辑:
- I cannot do a simple and direct dynamic_cast(p) because the type of p (or equivalently Shape1) will change at running time. This means that Shape1 can have "randomly" any derived type from 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
的指针并检查转换是否成功。
我想在执行时进行向下转换。
根据我的阅读,如果我想这样做,我需要将多态指针的 typeid
与派生的 classes 进行比较,然后以正确的方式进行转换类型。
另外,假设我有大量派生的 classes。
这意味着我必须写一个长 switch
或 if
.
我想通过使用 classes 的列表来检查来减少这项工作。
这可能看起来像:
#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 derived 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
呢?或者换句话说,我如何遍历 class 类型的列表以进行 typeid
比较和转换?
更多详情:
我同意在这个虚拟示例中,我可以简单地为每个派生的 class 覆盖一个函数,这是处理多态性的更好方法。但我需要沮丧,这是一个来自更复杂问题的约束,在这些问题中,我不允许更改它们。所以,这里的问题不是为什么沮丧,而是如何沮丧。
要提供有关我的约束的更多详细信息:
从基指针开始。
得到一个派生指针,交给一个外部函数(这里叫
function_only_for_Rectangle
,所以我不能修改这个函数)我不能做一个简单直接的
dynamic_cast<ClassRectangle>(p)
,因为p
(或等效的Shape1
)的类型会在运行时改变。这意味着Shape1
可以“随机地”拥有来自BaseShapes
的任何派生类型。所以我需要一些“自动”的东西,这就是为什么我考虑迭代所有派生类型并根据typeid
匹配进行向下转换(但我愿意接受更好的想法)。
如果需要,所有 classes 都可以修改。
你说“多态”,但你想做的恰恰相反
您可以实际使用它,而不是试图反对多态性。如果所有 subclasses 都有自己的虚函数实现,那么调用者不需要关心对象的实际动态类型是什么。简而言之就是运行时多态性。
我想 run
的命名只是为了举例。给它一个更好的名字,在基础 class 中提供默认实现,在 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;
}
关于您的编辑:
- I cannot do a simple and direct dynamic_cast(p) because the type of p (or equivalently Shape1) will change at running time. This means that Shape1 can have "randomly" any derived type from 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
的指针并检查转换是否成功。