说到C++类型转换不得不说,这是必须要弄清楚的一个东西,但是有特别容易弄错。
我们先用大字总结,以留下笔记再分析。
const_cast:
(1):<>括号里可以是对象,基本类型,以及他们的引用,和指针。
(2):作用就是把一个常量转换成一个全新变量返回给你,且保持和原来的常量的内存指向位置不变。
static_cast和dynamic_cast:
(1)调用虚函数时,认准对象创建的时候的类型,创建是什么类型就调他里面的虚函数
(2)调用普通函数,认准当前类型,使用当前类型的的函数
(3)子类->父类一般不会失败,推荐用static_cast
(4)父类->子类可能失败,为了安全应使用dynamic_cast,即使失败返回空指针
(5)父类->子类一旦使用dynamic_cast,则必须保证父类中有虚函数,否则编译失败;
(6)dynamic_cast<>里只能放非基本类型的引用或指针;
(7)dynamic_cast:继承关系的类指针对象或引用之间转换;
(8)static_cast:基本的数据类型转换和指针转换;
(9)const_cast:常量对象被转换成非常量对象,且保持指向不变;
const_cast 例子分析:
int a1=7;
const int *const p1=&a1;
这句话的正真意思是什么呢,不是官话什么“指向常量的常指针”,这句话话太不能理解了,实际上他就是告诉了我们以下两件事。
1. p1不能赋值
2. *p1也不能赋值
也就是说通过以上两种情况都不能改变a1在内存中值7,当然还有其他方法改变a1的值,比如a1自己赋值一个新的数值,这样也改变了内存中的值。
但是还有没有别的方法呢,这时候const_cast就可以发挥作用了。
int * p2 = const_cast<int*>(p1);//加上这句话,就可以利用p2来改变内存中a1的值了
static_cast和dynamic_cast例子源码
#include <iostream>
#define LOG(format,...) printf(format,__VA_ARGS__);//可变参数宏
class Base
{
public :
Base(){
a=5;
}
~Base(){}
int a;
virtual void display()
{
printf("virtualMethod:field a=%d\n",a);
}
void showInfo()
{
printf("normalMethod:field a=%d\n",a);
}
};
class Derived :public Base
{
public :
Derived(){
a=10;
}
~Derived(){}
int b;
virtual void display() override
{
printf("virtualMethod:field a=%d\n",a);
}
void showInfo()
{
printf("normalMethod:field a=%d\n",a);
}
};
int main()
{
LOG("\n\n子类->父类 非指针/ \n");
{
Derived p;
Base cp=p;
cp.display();
cp.showInfo();
Base cp1=static_cast<Base>(p);
cp1.display();
cp1.showInfo();
Base cp2=static_cast<Base&>(p);
cp2.display();
cp2.showInfo();
}
LOG("\n\n子类->父类 /*Base * obj=(Base *)(new Derived())]*/ \n");
{
Derived *p=new Derived();
Base *cp=(Base *)p;
cp->display();
cp->showInfo();
(*cp).display();
(*cp).showInfo();
delete p;
}
LOG("\n\n子类->父类/*Base * obj=static_cast<Base *>(new Derived())]*/\n");
{
//在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的
Derived *p=new Derived();
Base *cp=static_cast<Base *>(p);
cp->display();
cp->showInfo();
(*cp).display();
(*cp).showInfo();
delete p;
}
LOG("\n\n父类->子类/*Derived * obj=(Derived *)(new Base())]*/不安全的做法\n");
{
Base *p=new Base();
Derived *dp=(Derived *)p;
dp->display();
dp->showInfo();
(*dp).display();
(*dp).showInfo();
delete p;
}
LOG("\n\n父类->子类/*Derived * obj=static_cast<Derived *>(new Base())]*/不安全的做法\n");
{
Base *p=new Base();
Derived *dp=static_cast<Derived *>(p);
dp->display();
dp->showInfo();
(*dp).display();
(*dp).showInfo();
delete p;
}
LOG("\n\n父类->子类/*Derived * obj=dynamic_cast<Derived *>(new Base())]*/安全的做法\n");
{
Base *p=new Base();
Derived *dp=dynamic_cast<Derived *>(p);
if(dp!=nullptr)
{
dp->display();
dp->showInfo();
(*dp).display();
(*dp).showInfo();
}else
LOG("通过空指针判断出转换失败\n\n");
delete p;
}
LOG("\n\n子类->父类->子类=====================\n");
{
Derived *p2=new Derived();
Base *cp=static_cast<Base *>(p2);
Derived *dp=dynamic_cast<Derived*>(cp);
//Derived *dp=static_cast<Derived*>(cp);
dp->display();
dp->showInfo();
delete p2;
}
//LOG("\n\n子类2->父类2=====================\n");
//{
// Derived2 *p2=new Derived2();
// Base2 *cp=static_cast<Base2 *>(p2);
// Derived2 *dp=dynamic_cast<Derived2*>(cp);
// //Derived *dp=static_cast<Derived*>(cp);
// dp->showInfo();
// delete p2;
//}
LOG("=========C++继承关系总结=====================\n");
LOG("(1)调用虚函数时,谁new出来的对象,调用谁的虚函数\n");
LOG("(2)调用普通函数,目前这个是什么类调用\n");
LOG("(3)子类->父类一般不会失败,推荐用static_cast\n");
LOG("(4)父类->子类可能失败,为了安全应使用dynamic_cast,即使失败返回空指针\n");
LOG("(5)父类->子类一旦使用dynamic_cast,则必须保证父类中有虚函数,否则编译失败\n");
LOG("(6)dynamic_cast<>里只能放非基本类型的引用或指针\n");
LOG("(7)dynamic_cast:继承关系的类指针对象或引用之间转换,\n");
LOG("(8)static_cast:基本的数据类型转换和指针转换\n");
LOG("(9)const_cast:常量对象被转换成非常量对象,且保持指向不变\n");
}