获取基类指针指向什么派生类(typeid)

参考于 https://blog.csdn.net/gatieme/article/details/50947821

typeid关键字

注意:typeid是操作符,不是函数。这点与sizeof类似)

RTTI(Run-TimeType Identification, 运行时类型识别),它提供了运行时确定对象类型的方法。它使程序能够获取由基指针或引用所指向的对象的实际派生类型,即允许“用指向基类的指针或引用来操作对象”的程序能够获取到“这些指针或引用所指对象”的实际派生类型。

在C++中,为了支持RTTI提供了两个操作符:dynamic_cast和typeid

  1. dynamic_cast允许运行时刻进行类型转换,从而使程序能够在一个类层次结构中安全地转化类型
  2. typeid是C++的一个关键字,等同于sizeof这类操作符。typeid操作符的返回结果是名为type_info的标准库类型的对象的引用。type_info的name成员函数返回C-style的字符串。

实现机制与使用技巧

  1. 如果表达式的类型是类类型且至少包含有一个虚函数(由于此时的基类不具有多态性),则typeid操作符返回表达式的动态类型,需要在运行时计算,否则,typeid操作符返回表达式的静态类型,在编译时就可以计算。
  2. type_info类提供了public虚 析构函数,以使用户能够用其作为基类。它的默认构造函数和拷贝构造函数及赋值操作符都定义为private,所以不能定义或复制type_info类型的对象。程序中创建type_info对象的唯一方法是使用typeid操作符(由此可见,如果把typeid看作函数的话,其应该是type_info的 友元)。type_info的name成员函数返回C-style的字符串,用来表示相应的类型名,但务必注意这个返回的类型名与程序中使用的相应类型名并不一定一致(往往如此,见后面的程序),这具体由编译器的实现所决定的,标准只要求实现为每个类型返回唯一的字符串。

使用typeid时应注意:

(1)、typeid运算符允许在运行时确定对象的类型;

(2)、typeid的结果是const type_info&;

(3)、typeid运算符在应用于多态类类型的左值时执行运行时检查,其中对象的实际类型不能由提供的静态信息确定;

(4)、typeid也可在模板中使用以确定模板参数的类型;

(5)、typeid是操作符,不是函数,运行时获知变量类型名称;

(6)、要使用typeid,首先要确保编译器开启了运行时类型检查(RTTI)。

type_info类源代码

#ifndef _TYPEINFO
#define _TYPEINFO

#include <exception>

namespace std 
{

  class type_info 
  {
  public:

    virtual ~type_info();
    { return __name[0] == '*' ? __name + 1 : __name; }


    bool before(const type_info& __arg) const
    { return __name < __arg.__name; }

    bool operator==(const type_info& __arg) const
    { return __name == __arg.__name; }

    bool operator!=(const type_info& __arg) const
    { return !operator==(__arg); }

    virtual bool __is_pointer_p() const;

    virtual bool __is_function_p() const;

  protected:
    const char *__name;

    explicit type_info(const char *__n): __name(__n) { }

  private:
    type_info& operator=(const type_info&);
    type_info(const type_info&);
  };

} // extern "C++"
#endif

程序代码实例

#include <iostream>
using namespace std;
class Base
{
public:
	virtual void fun(){ cout << "this is Base fun call\n"; }; //此处有虚函数
};
class Derived:public Base
{
	//
};
class father
{
public:
	void fun()
	{
		cout << "this is father fun call\n";  //此处没有虚函数
	}
};
class son : public father
{
	//
};

int main()
{
	Derived derived;
	Base *p = new Base;
	p = &derived;
	son son1;
	father * fp = new father;
	fp = &son1;
	cout << "有虚函数:" << typeid(p).name() << "\t" << "没有虚函数:" << typeid(fp).name() << "\t" << "两种都是打印的是基类的指针类型" << endl;
	cout << "有虚函数:" << typeid(*p).name() << "\t" << "没有虚函数:" << typeid(*fp).name() << "\t" << "有虚函数打印的会根据运行时p所指向的实际类型去计算" << endl;
	cout << "有虚函数:" << typeid(Base).name() << "\t" << "没有虚函数:" << typeid(father).name() << "\t" << "both same" << endl;
	cout << "有虚函数:" << typeid(Derived).name() << "\t" << "没有虚函数:" << typeid(son).name() << "\t" << "both same" << endl;
	cout << "有虚函数:" << typeid(Base*).name() << "\t" << "没有虚函数:" << typeid(father*).name() << "\t" << "both same" << endl;
	cout << "有虚函数:" << typeid(Derived*).name() << "\t" << "没有虚函数:" << typeid(son*).name() << "\t" << "both same" << endl;
	system("pause");
	return 0;
}
有虚函数:class Base *   没有虚函数:class father *       两种都是打印的是基类的指针类型
有虚函数:class Derived  没有虚函数:class father 有虚函数打印的会根据运行时p所指向的实际类型去计算
有虚函数:class Base     没有虚函数:class father both same
有虚函数:class Derived  没有虚函数:class son    both same
有虚函数:class Base *   没有虚函数:class father *       both same
有虚函数:class Derived *        没有虚函数:class son *  both same
请按任意键继续. . .

代码解释

  1. 定义了一种Base基类带虚函数,继承于它的子类Derived。此实现方式具有多态性,在执行typeid().name()函数时,会动态的计算。如typeid§.name(),打印的是class Base *,当执行typeid(*p).name()时,打印的是classDerived,因为此时基类具有多态性,打印的是p真正所指向的对象,而本例中p指向的是派生类对象,现在p真正指向的是其子类Derived,所以打印的是class Derived。*因此表达式typeid(p) == typeid(derived)为真
  2. 第二种是不带虚函数的基类father,所以执行的结果本质是没有区别的。
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值