代码及说明:
main.cpp
#include
#include
#include
#include "rtti1.h"
using std::cout;
using std::endl;
Grand *GetOne();
void change(const int *pt, int n);
int main()
{
/*
dynamic_cast:
dynamic_cast是最常用的RTTI操作符。
回答的问题:是否能将某个对象的地址安全地赋值给一个特定类型的指针;同时也回答了强制类型转换是否安全的问题
格式:dynamic_cast(pt)
pt能否安全的类型转换(*pt为Type或者*pt为Type的继承类)为Type *,如果可以,则返回pg的地址;反之,返回0
也可以使用引用(应该不常用):dynamic_cast(rg)
pt能否安全的类型转换(pt为Type或者pt为Type的继承类)为Type &,如果可以,则返回pg的地址;反之,引发bad_cast异常(在typeinfo头文件中)
*/
cout << "dynamic_cast***************************************************************" << endl;
std::srand(std::time(0));
Grand *pg;
Superb *ps;
for (int i = 0; i < 5; i++)
{
pg = GetOne();
pg->Speak();
if (ps = dynamic_cast<Superb *>(pg)) // 如果可以转换,则if条件判断为1,则执行ps->Say();反之,不执行
ps->Say();
}
/*
const_cast:
转换格式:const_cast < type-name > (expression)
要求:type-name和expression必须是同一种类型,他们只在const和volatile上存在区别,转换成功就赋值就行,转换失败则返回0
与常规类型转换的不同:常规类型转换可以转换为不同类型,但是const_cast不允许不同类型的转换
基本原则:不允许将定义为const的变量转换为非const类型。
*/
cout << "const_cast***************************************************************" << endl;
int pop1 = 38383;
const int pop2 = 2000;
cout << "pop1, pop2: " << pop1 << ", " << pop2 << endl;
change(&pop1, -103); // 转换了,因为pop1是非const类型
change(&pop2, -103); // 没转换,因为pop2是const类型
cout << "pop1, pop2: " << pop1 << ", " << pop2 << endl;
/*
static_cast:
格式:static_cast < type-name > (expression)
当且仅当type-name类型可以隐式转换为expression类型,或反之,否则类型转换会报错,两者能互相转换
1.允许向上转换(继承类指针转换为基类指针)
2.允许向下转换(基类指针转换为继承类指针)
3.由于枚举类可以隐式转换为int,因此static_cast允许这类转换,并且允许将int类型转换为枚举类
4.允许将double转换为int,将int转换为double
5.允许将float转换为long,允许将long转换为float
*/
cout << "static_cast***************************************************************" << endl;
Grand x = Grand(10); // 基类对象
Grand *w = &x; // 基类指针
Superb z = Superb(11); // 继承类对象
Superb *pointer1 = &z;
Superb *y = static_cast<Superb *>(w); // 将基类指针转换为继承类指针 允许
y->Speak(); // 只是允许但是不推荐,因为转换为继承类指针后可以调用继承类的成员方法,而基类没有该成员方法,会引发异常
Grand *a = static_cast<Grand *>(pointer1); // 将继承类指针转换为基类指针
a->Speak();
int varint1 = 99;
double vardouble1 = 99.99;
int var = static_cast<int>(vardouble1);
std::cout << "var = " << var << std::endl;
double var1 = static_cast<double>(varint1);
std::cout << std::fixed << "var1 = " << var1 << std::endl;
/*
reinterpret_cast:
格式:reinterpret_cast < type-name > (expression)
可以将指针类型转换为能够容纳该指针类型的整型,反之不能转换。
不能将函数指针转换为数据指针
*/
struct dat
{
short a;
short b;
};
long value = 0xA224B118;
dat *pd = reinterpret_cast<dat *>(&value);
std::cout << std::hex << pd->a; // display first 2 bytes of value
return 0;
}
Grand *GetOne() // generate one of three kinds of objects randomly
{
Grand *p = 0;
switch (std::rand() % 3)
{
case 0:
p = new Grand(std::rand() % 100);
break;
case 1:
p = new Superb(std::rand() % 100);
break;
case 2:
p = new Magnificent(std::rand() % 100,
'A' + std::rand() % 26);
break;
}
return p;
}
void change(const int *pt, int n)
{
int *pc;
pc = const_cast<int *>(pt);
*pc += n;
}
rtti1.h
#pragma once
#include
using std::cout;
#ifndef _RTTI1_H_
#define _RTTI1_H_
class Grand
{
private:
int hold;
public:
Grand(int h = 0) : hold(h) {}
virtual void Speak() const { cout << "I am a grand class!\n"; }
virtual int Value() const { return hold; }
};
class Superb : public Grand
{
public:
Superb(int h = 0) : Grand(h) {}
void Speak() const { cout << "I am a superb class!!\n"; }
virtual void Say() const
{
cout << "I hold the superb value of " << Value() << "!\n";
}
};
class Magnificent : public Superb
{
private:
char ch;
public:
Magnificent(int h = 0, char c = 'A') : Superb(h), ch(c) {}
void Speak() const { cout << "I am a magnificent class!!!\n"; }
void Say() const
{
cout << "I hold the character " << ch << " and the integer " << Value() << "!\n";
}
};
#endif