C++ 语法实验室之const_cast,static_cast,dynamic_cast

说到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");

}







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章