C++ 基础类型转换。最好不用强转,必须要转用以下4种

main.cpp

// ConsoleApplicationC++jichu3.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "Man.h"
#include "Human.h"
#include "iostream"
using namespace std;
void zhiZhenStatic_castFunc(){
	//-- 指针类型的转换
	//Men *m = new Men;
	Men m;
	Human *hp = &m;
	//-- 利用多态,调用子类的函数。
	hp->testParentVirtualFunc();
	Men *mTemp = dynamic_cast<Men*>(hp);
	if (mTemp != nullptr) {
		//-- 如果转换成功,就说明指针hp 是要转换到的那个类型(如上面的hp就是Men类型指针),所以dynamic_cast运算符是帮助做类型检查的。
		mTemp->testDynamicCastFunc();
	}
	else {
		//-- 转换失败
		cout << "ph指针实际上指向的不是一个Men类型对象" << endl;
	}
	//-- 测试二
	Human th;
	Men *pm = dynamic_cast<Men*> (&th);
	if (pm != nullptr)
	{
	    //--不会执行到这
		pm->testDynamicCastFunc();
		pm->testParentVirtualFunc();
	}
	else {
		cout << "转换失败,不能将父类指针转成子类指针,可以进行转换,但是发现转换后pm是null" << endl;
	}

}
void yinYongStatic_castFunc(){
	//-- 引用类型的转换
	Men m;
	Human &hp = m;
	//-- 利用多态,调用子类的函数。
	hp.testParentVirtualFunc();
	
	try
	{
		Men &mTemp = dynamic_cast<Men&>(hp);
		//-- 走到这里表示转换成功
		cout << "hp实际上是一个Men类型" << endl;
		//-- 这里操作Men类里的成员函数、成员变量等都是安全的
		mTemp.testDynamicCastFunc();
	}
	catch (bad_cast)
	{
		//-- 转换失败
		cout << "hp不是一个Men类型" << endl;
	}
}

void typeidTest(){
	//-- 使用typeid运算符其实是为了比较两个指针是否指向同一种类型
	Human *ph = new Human;
	Human *ph1 =  new Men;
	Men *m = new Men;
	//-- typeid运算符返回的是 一个常量对象的引用 , 这个对象是type_info类 (类类型)。
	if (typeid(ph) == typeid(ph1))
	{
		//-- ph 和 ph1指针定义时类型相同 运算的值就相等
		cout << "ph和ph1指向同一种类型" << endl; //OK
	}
	if (typeid(m) == typeid(ph1))
	{
		cout << "m和ph1指向同一种类型" << endl; 
	}
	else {
		cout << "m和ph1 不是指向同一种类型" << endl;//OK
	}

	if (typeid(*m) == typeid(*ph1))
	{
		//-- m 和 ph1指针运行时指向的类型相同 运算的值就相等
		cout << "*m和*ph1指向同一种类型" << endl; //OK
	}

	if (typeid(Human*) == typeid(ph))
	{
		cout << "ph是Human*类型" << endl; //OK
	}
	if (typeid(Human*) == typeid(ph1))
	{
		cout << "ph1是Human*类型" << endl; //OK
	}
	if (typeid(Men) == typeid(*ph1))
	{
		cout << "ph1是Men类型" << endl; //OK
	}
	//-- 要想让上面的这些例子得到正确的结果,父类必须要有虚函数,只有当父类有虚函数时,编译器才会对typeid中的表达式进行求值,否则typeid返回的是 表达式(参数)定义时的类型。
	delete m;
	delete ph1;
	delete ph;
	ph = nullptr;
}
int _tmain(int argc, _TCHAR* argv[])
{
	//-- static_cast
	int ia = static_cast<int>(12.346);
	int b = 100;
	void * p = &b;
	int * q = static_cast<int*> (p);
	//-- reinterpret_cast
	char * r = reinterpret_cast<char *>(q); //把100 变成了b
	//-- const_cast
	int const c = 100;
	*const_cast<int*>(&c) = 200;


	//-- 使用dynamic_cast的前提条件:父类中 必须至少有一个 虚函数。
	//-- RITT:运行时类型识别功能,通过dynamic_cast 将父类的指针或者引用 安全地转换为子类的指针或者引用。和typeid运算符,返回指针或者引用所指对象的实际类型。

	//-- 如果父类指针调用 子类中的普通成员函数, 方式一:父类也将写入此函数,并写成虚函数。
	//-- 方式二:使用dynamic_cast运算符进行类型转换,将基类 指针 或者 引用 转成子类 的指针或者引用,
	//-- 我们要清楚的知道转换的目标类型,并且 转换类型后 还需要检查这种转换是否成功

	//-- 指针类型的转换
	zhiZhenStatic_castFunc();
	//-- 引用类型的转换
	yinYongStatic_castFunc();

	typeidTest();
	return 0;
}

//-- void* 严格限制,不能赋值给替他地址类型
//类型转换:不提倡强转。
/*
1.static_cast<类型>(数据)        用于数值类型之间,以及void*和别的*类型之间
2.const_cast<T*>(T常量的地址)    去掉对地址所指向目标的const限制
3.dynamic_cast<类型>(数据) 父子类之间,父类中必须要有一个虚函数
4.reinterpret_cast<类型>(数据)  用于数值类型与地址类型之间,或者地址类型相互之间
*/
//english   interpret解释

human.h

#pragma once
class Human
{
public:
	virtual void testParentVirtualFunc();
protected:
private:
};

human.cpp

#include "stdafx.h"
#include "Human.h"
#include "iostream"
using namespace std;
void Human::testParentVirtualFunc(){
	cout << ":基类的成员函数 testParentVirtualFunc" << endl;
}

Man.h

#pragma once
//class Human;  //能定义Human * p;成员。    不能定义Human  p;成员  不能继承
#include "Human.h" //能定义Human * p;成员。    也能定义Human  p;成员。  也能继承
class Men :public Human
{
public:
	void testDynamicCastFunc();
	virtual void testParentVirtualFunc();
private:
};


Man.cpp

#include "stdafx.h"
#include "Man.h"
#include "iostream"
using namespace std;
void Men::testDynamicCastFunc(){
	cout << ":子类的成员函数 testDynamicCastFunc" << endl;
}

void Men::testParentVirtualFunc(){
	cout << ":子类的成员函数 testParentVirtualFunc" << endl;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值