码迷,mamicode.com
首页 > 编程语言 > 详细

【C/C++】【类和对象】RTTI和虚函数表

时间:2020-07-21 09:35:20      阅读:87      评论:0      收藏:0      [点我收藏+]

标签:rtu   编译器   ESS   运算   vat   code   dba   静态   ide   

RTTI是什么

Run Time Type Identification:运行时类型识别;通过运行时类型识别,程序能够使用基类的指针或引用来检查这些指针或引用所指向的对象的实际派生类型。

Human *phuman = new Men;
Human &q = *phuman;

主要是通过两个运算符来实现的:

  1. dynamic_cast:能够将基类指针或者引用安全的转换为派生类的指针或者引用;
  2. typeid:返回指针或者引用所指对象的实际类型;
    注意
    要想让1和2正常工作,那么基类中必须至少有一个虚函数,否则这两个运算符的结果可能跟我们预想的不一样;因为只有虚函数的存在,这两个运算符才会使用指针或者引用所绑定的对象的动态类型(new的类型);

dynamic_cast

指针,如果转换成功,说明这个指针实际上是要转换到的那个类型;会做安全检查;

#include <iostream>
using namespace std;
class Human
{
public:
	Human();
	Human(int);
	virtual ~Human();
public:
	int m_Age;
	char m_Name[100];
public:
	virtual void eat() =0;
};
Human::Human()
{
	cout << "Human::Human()" << endl;
}
Human::~Human()
{
	cout << "Human::~Human()" << endl;
}
Human::Human(int tmp)
{
	cout << "Human::Human(int tmp)" << endl;
}
//Men是Human的子类
class Men:public Human
{
public:
	Men();
	Men(int);
	~Men();
private:

public:
	virtual void eat();
};
Men::Men()
{
	cout << "Men::Men()" << endl;
}
Men::~Men()
{
	cout << "Men::~Men()" << endl;
}

Men::Men(int tmp)
{
	cout << "Men::Men(int tmp)" << endl;
}
void Men::eat()
{
	cout << "men eat mi" << endl;
}
//Women是Human的子类
class Women :public Human
{
public:
	Women();
	Women(int);
	~Women();
private:

public:

	virtual void eat();
};

Women::Women()
{
	cout << "Women::Women()" << endl;
}
Women::~Women()
{
	cout << "Women::~Women()" << endl;
}

Women::Women(int tmp)
{
	cout << "Women::Women(int tmp)" << endl;
}


void Women::eat()
{
	cout << "women eat miantiao" << endl;
}
int main()
{
	//Men men;

	Human* p_m = new Men;
	Men* p_men = dynamic_cast<Men*>(p_m);
	if (p_men != nullptr)
		cout << "cast success! p_men is Men*" << endl;
	else
		cout << "cast fail! p_men is not Men*" << endl;
}

引用,如果用dynamic_cast转换失败,系统会抛出一个std::bad_cast异常;

#include <iostream> 
using namespace std;
class Human
{
public:
	Human();
	Human(int);
	virtual ~Human();
public:
	int m_Age;
	char m_Name[100];
public:
	virtual void eat() =0;
};

Human::Human()
{
	cout << "Human::Human()" << endl;
}
Human::~Human()
{
	cout << "Human::~Human()" << endl;
}

Human::Human(int tmp)
{
	cout << "Human::Human(int tmp)" << endl;
}




//Men是Human的子类
class Men:public Human
{
public:
	Men();
	Men(int);
	~Men();
private:

public:
	virtual void eat();
};

Men::Men()
{
	cout << "Men::Men()" << endl;
}
Men::~Men()
{
	cout << "Men::~Men()" << endl;
}

Men::Men(int tmp)
{
	cout << "Men::Men(int tmp)" << endl;
}


void Men::eat()
{
	cout << "men eat mi" << endl;
}


//Women是Human的子类
class Women :public Human
{
public:
	Women();
	Women(int);
	~Women();
private:

public:

	virtual void eat();
};

Women::Women()
{
	cout << "Women::Women()" << endl;
}
Women::~Women()
{
	cout << "Women::~Women()" << endl;
}

Women::Women(int tmp)
{
	cout << "Women::Women(int tmp)" << endl;
}


void Women::eat()
{
	cout << "women eat miantiao" << endl;
}


int main()
{

	//引用
	Human* phuman = new Men;
	Human& q = *phuman;
	try
	{
		Men& m = dynamic_cast<Men&>(q);
	}
	catch(std::bad_cast) //转换不成功
	{
		cout << "p is not Men!" << endl;
	}

	return 0;
}

typeid运算符

typeid(类型[指针/引用]/表达式);//得到对象类型信息

typeid会返回一个常量对象的引用,这个常量对象是一个标准库类型type_info(类/类类型);

#include <iostream>
using namespace std;
class Human
{
public:
	Human();
	Human(int);
	virtual ~Human();
public:
	int m_Age;
	char m_Name[100];
public:
	virtual void eat() =0;
};

Human::Human()
{
	cout << "Human::Human()" << endl;
}
Human::~Human()
{
	cout << "Human::~Human()" << endl;
}
Human::Human(int tmp)
{
	cout << "Human::Human(int tmp)" << endl;
}
//Men是Human的子类
class Men:public Human
{
public:
	Men();
	Men(int);
	~Men();
private:

public:
	virtual void eat();
};

Men::Men()
{
	cout << "Men::Men()" << endl;
}
Men::~Men()
{
	cout << "Men::~Men()" << endl;
}

Men::Men(int tmp)
{
	cout << "Men::Men(int tmp)" << endl;
}
void Men::eat()
{
	cout << "men eat mi" << endl;
}
//Women是Human的子类
class Women :public Human
{
public:
	Women();
	Women(int);
	~Women();
private:

public:
    virtual void eat();
};
Women::Women()
{
	cout << "Women::Women()" << endl;
}
Women::~Women()
{
	cout << "Women::~Women()" << endl;
}
Women::Women(int tmp)
{
	cout << "Women::Women(int tmp)" << endl;
}
void Women::eat()
{
	cout << "women eat miantiao" << endl;
}
int main()
{
	//引用
	Human* phuman = new Men;
	Human& q = *phuman;
	cout << typeid(*phuman).name() << endl;
	cout << typeid(q).name() << endl;
    
        //1. typeid判断两个指针指向的是否是同一种类型的对象
        Human* phuman_1 = new Men;
	Human* phuman_2 = new Women;
	//比较对象,看的是new出来的是哪个对象或者该指针指向的是哪个对象,和定义该指针是定义的类型无关;
	//不要忘记*,解引用;
	if (typeid(*phuman_1) == typeid(*phuman_2)) //不成立
		cout << "same!" << endl;
	else
		cout << "not same!" << endl;
	
	if (typeid(*phuman_1) == typeid(Men))
		cout << "puhuman_1 is Men" << endl;
        //基类必须要有虚函数,否则上述条件不成立;
        //如果基类中不含虚函数,那么typeid返回的是表达式的静态类型;
	return 0;
}

type_info类

typeid就返回一个常量对象的引用,这个常量对象是一个标准库类型type_info(类/类类型)

#include <iostream>
using namespace std;
class Human
{
public:
	Human();
	Human(int);
	virtual ~Human();
public:
	int m_Age;
	char m_Name[100];
public:
	virtual void eat() =0;
};

Human::Human()
{
	cout << "Human::Human()" << endl;
}
Human::~Human()
{
	cout << "Human::~Human()" << endl;
}

Human::Human(int tmp)
{
	cout << "Human::Human(int tmp)" << endl;
}
//Men是Human的子类
class Men:public Human
{
public:
	Men();
	Men(int);
	~Men();
private:

public:
	virtual void eat();
};

Men::Men()
{
	cout << "Men::Men()" << endl;
}
Men::~Men()
{
	cout << "Men::~Men()" << endl;
}

Men::Men(int tmp)
{
	cout << "Men::Men(int tmp)" << endl;
}
void Men::eat()
{
	cout << "men eat mi" << endl;
}
//Women是Human的子类
class Women :public Human
{
public:
	Women();
	Women(int);
	~Women();
private:

public:

	virtual void eat();
};

Women::Women()
{
	cout << "Women::Women()" << endl;
}
Women::~Women()
{
	cout << "Women::~Women()" << endl;
}

Women::Women(int tmp)
{
	cout << "Women::Women(int tmp)" << endl;
}
void Women::eat()
{
	cout << "women eat miantiao" << endl;
}
int main()
{
	//name
	Human* phuman = new Men;
	const type_info& tp = typeid(*phuman);
	cout << tp.name() << endl;

	//== !=
	
	return 0;
}

RTTI与虚函数表

  • C++中,如果类含有虚函数,编译器会对该类产生一个虚函数表;
  • 虚函数表中有很多项,每一项都是一个指针,每个指针指向的是这个类里的各个虚函数的入口地址;
  • 虚函数表项里,第一个表项很特殊,他指向的不是虚函数的入口地址,指向的实际上是咱们这个类所关联的type_info对象;
int main()
{
	Human* phuman = new Men;
	const type_info& tp = typeid(*phuman);
	//phuman对象里有一个指针,指向这个对象所在的类Men里的虚函数表
	return 0;
}

【C/C++】【类和对象】RTTI和虚函数表

标签:rtu   编译器   ESS   运算   vat   code   dba   静态   ide   

原文地址:https://www.cnblogs.com/Trevo/p/13343848.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!