如何找出变量的类型,包括继承/多态性
How to find out the type of a variable, with inheritance/polymorphism involved
当涉及继承时,如何找出变量的类型?
我有一个小情况,我将用伪代码描述:
class A
{
public:
A();
virtual ~A();
protected:
//some members
};
class B : public A
{
public:
B();
virtual ~B();
protected:
//some members
};
///////////////////////
int main()
{
A* pA = new B();
std::cout<<"type of pA: "<< ???;
}
我怎样才能找到pA的类型?结果应该是B。另外,如果我希望结果是A,我该怎么办?
谢谢。
编辑:
我让你来判断这是不是糟糕的设计。如果你认为是的话,请告诉我一个更好的选择。
代码:
class MyContactReport : public NxUserContactReport
{
void OnContactNotify(NxContactPair& pair, NxU32 events)
{
if (pair.actors[0]->userData == NULL || pair.actors[1]->userData == NULL) return;
LevelElement* otherObject = (LevelElement*)pair.actors[1]->userData;
LevelElement* triggerObject = (LevelElement*)pair.actors[0]->userData;
switch(events)
{
case NX_NOTIFY_ON_START_TOUCH:
triggerObject->OnContactStartTouch(otherObject);
break;
case NX_NOTIFY_ON_END_TOUCH :
triggerObject->OnContactEndTouch(otherObject);
break;
case NX_NOTIFY_ON_TOUCH:
triggerObject->OnContactTouch(otherObject);
break;
}
}
} *myReport;
pair.actors[1]->userData
允许我从actor访问userData,actor是PhysX框架的一部分,用于确定碰撞和物理等。用户数据的类型为void*
。这也是找出行动者实际所属对象的唯一方法
然后是class LevelElement
,一个抽象类,我的级别中的每个对象都继承自(游戏级别中的级别)
LevelElement具有受保护的虚拟方法:OnContactTouch(LevelElement* pOtherElement)
等。。。在这些方法中,我需要弄清楚它是什么类型的LevelElement,以采取某些具体措施。
这个设计不好吗?如果是,请帮忙!
使用typeid运算符,例如此处所述。
基本上:
#include <typeinfo>
[…]
std::cout << "typeid(*pA): " << typeid(*pA).name() << std::endl;
std::cout << "typeid(pA): " << typeid(pA).name() << std::endl;
结果,g++4.4.5:
typeid(*pA): 1B
typeid(pA): P1A
也就是说,至少在使用gcc时会有一些混乱。看看这个问题,了解如何处理这个问题。
编辑:对于你的设计问题,与其检查另一个object是什么类型,更好的解决方案是告诉这个对象该做什么。假设你想为一个假设的Bullet对象编码onContactTouch;而不是
switch (type) {
case PLAYER:
(Player*)otherObject->dealDamage(10);
break;
case BULLETPROOF_GLASS:
(BulletproofGlass*)otherObject->ricochet();
break;
}
这样做:
otherObject->onHitByBullet(this);
这有时被称为"告诉,不要问"原则。
严格来说,这并不是糟糕设计的症状。尽管您当然可以从类型检查中抽象出类型。为了性能和运行时自定义,您几乎绝对不应该使用RTTI或其他直接类型检查系统。实现自己的(简化得多的)类型检查动态允许对象在对象级别而不是类级别定义碰撞行为,并在运行时重新定义碰撞行为。
//PSEUDO CODE
enum CollisionTypes = {HARD_THING, SOFT_THING, EXPLODING_THING};
class FragileThing is a GameObject
{
public function getCollisionType()
{
return SOFT_THING;
}
public function collideWith(GameObject obj)
{
if (obj.getCollisionType() == SOFT_THING)
print "whew...";
else
print "OUCH!";
}
}
class CollisionDispatcher is a PhysXCollisionListener
{
public function getCollisionFromPhysX(Collision col)
{
col.left.collideWith(col.right);
col.right.collideWith(col.left);
}
}
我在书中看到的另一个系统是使用引擎范围的消息传递框架来调度与嵌入消息中的类型信息的冲突。不相关的类型可以简单地忽略消息。不过我还没试过。我还建议检查LevelObject类,以确定是否没有可以添加到其中的某种通用功能来避免这个问题。例如,如果对象的基本类型很少(可能是红色和绿色,或者以太、软、硬、爆炸),那么您可以将这些类型编码为函数调用,而不是条件语句:function collideWithSomethingHard(LevelObject obj)
,从而允许对象只定义它们关心的碰撞行为。希望这能有所帮助。
如果您需要这样做,那么很可能您的接口缺乏或设计得不够理想。相反,重新访问您的接口,并提供一组适当的(可能是抽象的)虚拟方法来实现所需的接口。那么你就不需要担心特定的子类型了。
如果您真的需要信息,您可以使用typeid
,如@Emil Styrke 的答案所示
使用函数typeid(pA).name()
时。结果是CCD_ 8。
// typeid
#include <iostream>
#include <typeinfo>
using namespace std;
class A
{
public:
A(){}
virtual ~A(){}
protected:
};
class B : public A
{
public:
B(){}
virtual ~B(){}
protected:
};
int main()
{
A* pA = new B();
cout<<"The expression [A* pA = new B()]: n";
cout<<"Has datatype --> "<< typeid(pA).name() <<"<-- n";
cout<<" n";
return 0;
}
输出:
The expression [A* pA = new B()]:
Has datatype --> class A *<--
Press any key to continue
- 继承函数的重载解析
- 继承期间显示未知行为的子类
- 头文件-继承c++
- 为什么在保护模式下继承升级不起作用
- 通过继承类使用来自不同命名空间的运算符
- 子目录是否继承属性,例如add_definitions,include_directories和父Cmakelist.t
- 从矢量<无符号字符>转换为字符* 包括垃圾数据
- Windows 10-使用gtkmm-3.0库和g++[包括再现]的分段故障
- 混合组合和继承的C++问题
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 为什么 cmake 许可证<>样式不包括?
- 从类继承时,继承的类是否会通过父类重新定义继承的变量
- 公共与私人继承
- C++继承 - 覆盖功能,包括使用 "::" s、.h 文件和.cpp文件
- 在另一个项目中包括继承的类时,抽象类的链接器错误
- 如果对象是堆栈创建的(包括继承的类型),是否可以发出编译错误
- 如何找出变量的类型,包括继承/多态性
- 是否有任何cpp函数或对象(不包括从c继承的)不是线程安全的,即使每个线程对自己的数据进行操作
- 继承 std::容器,包括其提升序列化
- 当类包括复制构造函数和赋值运算符时继承的行为