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;
}