【c++】——c++的四种类型转换

1、const_cast

他的主要作用就是去掉(指针或者引用)常量属性的类型转换。

例如,当我们想将一个常量a的指针转成一个int*,在c语言中可以用如下的方式强制转换。

int main()
{
   const int a = 10;
	int* p = (int*)&a;
	return 0;
}

但是在c++中,我们就有了const_cast,就可以使用如下的方式转换:

int main()
{
   const int a = 10;
   int* p2 = const_cast<int*>(&a);
	return 0;
}

可以将其看成一个模板,在模板里面提供转换成的类型

注意!!

  1. 上述两种转换在底层(转成汇编指令过后)实现是一模一样的
  2. char* p = (char*)&a;是可以的,但是char* p2 = const_cast<char*>(&a);是不可以的。因为,const_cast在提供强转的时候,需要表达式(地址类型)与左边定义的类型,包括要转换的类型应该保持一致。防止了任意转换类型导致一些不可预期的问题。
  3. const_cast<引用这里面必须是指针或引用类型 int int&*>

2、static_cast

他的主要作用是提供编译器认为安全的类型转换(没有任何联系的类型之间的转换就被否定了),也是我们最常用的一种转换方式。

例如,如果像下面这样写编译器就会直接报错

int *p = nullptr;
short* b = static_cast<short*>(a); 

另外,基类类型 <=>派生类类型 可以用static_cast转换

3、reinterpret_cast

他的作用就类似于c风格的强制类型转换。你想要怎样转换都可。

4、dynamic_cast

他的主要作用是用在继承结构中,可以支持RTTI类型识别的上下转换

为了更好的解释他的作用,我们先实现一个继承的代码如下:

class Base
{
public:
	virtual void func() = 0; 
};
class Derive1 :public Base
{
public:
	void func() { cout << "call Derive1::func" << endl; }
};
class Derive2 :public Base
{
public:
	void func() { cout << "call Derive2::func" << endl; }
};
void showFunc(Base* p)
{
		p->func();//动态绑定
}
int main()
{
	Derive1 d1;
	Derive2 d2;
	showFunc(&d1);
	showFunc(&d2);
	return 0;
}

运行结果如下:
在这里插入图片描述
上述代码都实现的是动态绑定,最后输出自己对应的函数。
但是当我们的需求改变,当访问到Derive2对象时,要实现Derive02func()方法时应该怎么办呢?
首先,需求更改了 Derive2实现新功能的API接口函数如下:

class Derive2 :public Base
{
public:
	void func() { cout << "call Derive2::func" << endl; }
	void Derive02func() { cout << "call Derive02func::func" << endl; }
};

接下来就思考void showFunc(Base* p)里面如何修改了。
因为需求改变了,当访问到Derive2对象时,要实现Derive02func()方法,所以要关注*p的类型
在我们之前所学的知识里面可以用

typeid(*p).name() == "Derive2"

来进行一个类型的比较,但是这样不好。

这时就要提出我们的dynamic_cast类型转换了。

Derive2* pd2 = dynamic_cast<Derive2*>(p);

把p类型的指针转成Derive2* 类型的指针dynamic_cast会检查p指针是否指向的是一个Derive2类型的对象。通过p 访问vfptr进而访问对象的vftable 里面存放了RTTI信息 如果是dynamic_cast转换类型成功,返回Derive2对象的地址,给pd2,否则返回nullptr

因此,void showFunc(Base* p)里面代码实现如下:

void showFunc(Base* p)
{
	Derive2* pd2 = dynamic_cast<Derive2*>(p);
	if (pd2 != nullptr)
	{
		pd2->Derive02func();
	}
	else
	{
		p->func();//动态绑定
	}
}

运行结果如下:
在这里插入图片描述
由此可以看出static_cast编译时期的类型转换,dynamic_cast运行时期的类型转换,支持RTTI信息识别的

发布了98 篇原创文章 · 获赞 9 · 访问量 3661

猜你喜欢

转载自blog.csdn.net/qq_43412060/article/details/105249803