gitee仓库:https://gitee.com/tgwTTT/c-lreant/tree/master/c++Type%20conversion

1. C中的类型转换

在C语⾔中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回值类型不⼀致时等场景,就需要发⽣类型转化,C语⾔中总共有两种形式的类型转换:隐式类型转换和显式强制类型转换。

1. 隐式类型转化:编译器在编译阶段⾃动进⾏,能转就转,不能转就编译失败2

2.显式强制类型转化:需要⽤⼾⾃去显⽰在变量前⽤括号指定要转换的类型•

并不是任意类型之前都⽀持转换,两个类型⽀持转换需要有⼀定关联性,也就是说转换后要有⼀定的意义,两个毫⽆关联的类型是不⽀持转换的。

如下面:

1.隐式类型转化主要是:浮点数和整形之间,浮点数和浮点数,整数和整数

2.显示类型转化主要是:主要发生在指针和整形之间,指针和指针之间

int main() {
	int i = 1;
	double d = i;
	int* p = &i;
	int addr = (int)p;
	//malloc返回的是void*,被强转成int*
	//int* ptr = (int*)malloc(8);
	cout << sizeof(*(void**)p) << endl;
	cout << p << endl;
	cout << addr;
	return 0;
}

2.c++中的类型转化

1.C++兼容C,所以C⽀持的隐式类型转换和显式强制类型转换C++都⽀持。

2.C++还⽀持内置类型到⾃定义类型之间的转换,内置类型转成⾃定义类型需要构造函数的⽀持,⾃定义类型转成内置类型,需要⼀个operator 类型()的函数去⽀持。

3.C++还⽀持⾃定义类型到⾃定义类型之间的转换,需要对应类型的构造函数⽀持即可,⽐如A类型对象想转成B类型,则⽀持⼀个形参为A类型的B构造函数即可⽀持。

#include 
using namespace std;
// 内置类型和⾃定义类型之间
// 1、⾃定义类型 = 内置类型 ->构造函数⽀持
// 2、内置类型 = ⾃定义类型 ->operator 内置类型 ⽀持
class A
{
public:
	// 构造函数加上explicit就不⽀持隐式类型转换了
	//explicit A(int a)
	A(int a)
		:_a1(a)
		, _a2(a)
	{}
	A(int a1, int a2)
		:_a1(a1)
		, _a2(a2)
	{}
	// 加上explicit就不⽀持隐式类型转换了
	// explicit operator int()
	operator int() const
	{
		return _a1 + _a2;
	}
private:
	int _a1 = 1;
	int _a2 = 1;
};
class B
{
public:
	B(int b)
		:_b1(b)
	{}
	// ⽀持A类型对象转换为B类型对象
	B(const A& aa)
		:_b1(aa)
	{}
private:
	int _b1 = 1;
};
int main()
{
	// 单参数的转换
	string s1 = "1111111";
	A aa1 = 1;
	A aa2 = (A)1;
	// 多参数的转换
	A aa3 = { 2,2 };
	const A& aa4 = { 2,2 };
	int z = aa1.operator int();
	int x = aa1;
	int y = (int)aa2;
	cout << x << endl;
	cout << y << endl;
	cout << z << endl;
	std::shared_ptr foo;
	std::shared_ptr bar(new int(34));
	//if (foo.operator bool())
	if (foo)
		std::cout << "foo points to " << *foo << '\n';
	else
		std::cout << "foo is null\n";
	if (bar)
		std::cout << "bar points to " << *bar << '\n';
	else
		std::cout << "bar is null\n";
	// A类型对象隐式转换为B类型
	B bb1 = aa1;
	B bb2(2);
	bb2 = aa1;
	const B& ref1 = aa1;
	return 0;
}

3.类型安全

1. 类型安全是指编程语⾔在编译和运⾏时提供保护机制,避免⾮法的类型转换和操作,导致出现⼀个内存访问错误等,从⽽减少程序运⾏时的错误

2. C语⾔不是类型安全的语⾔,C语⾔允许隐式类型转换,⼀些特殊情况下就会导致越界访问的内存错误,其次不合理的使⽤强制类型转换也会导致问题,⽐如⼀个int*的指针强转成double*访问就会出现越界。

3. C++兼容C语⾔,⽀持隐式类型转换和强制类型转换,C++也不是类型安全的语⾔,C++提出4个显⽰的命名强制类型转换static_cast/reinterpret_cast/const_cast/dynamic_cast就是为了让类型转换相对⽽⾔更安全。

4.4种显示的命名强制类型转换

1.tatic_cast⽤于两个类型意义相近的转换,这个转换是具有明确定义的,只要底层不包含const,都可以使⽤static_cast。

2.reinterpret_cast⽤于两个类型意义不相近的转换,reinterpret是重新解释的意思,通常为运算对象的位模式提供较低层次上的重新解释,也就是说转换后对原有内存的访问解释已经完全改变了,⾮常的⼤胆。所以我们要谨慎使⽤,清楚知道这样转换是没有内存访问安全问题的。

3. const_cast⽤于const类型到⾮const类型的转换,去掉了const属性,也是⼀样的我们要谨慎使⽤,否则可能会出现意想不到的结果。

4.dynamic_cast⽤于将基类的指针或者引⽤安全的转换成派⽣类的指针或者引⽤。如果基类的指针或者引⽤时指向派⽣类对象的,则转换回派⽣类指针或者引⽤时可以成功的,如果基类的指针指向基类对象,则转换失败返回nullptr,如果基类引⽤指向基类对象,则转换失败,抛出bad_cast异常。 其次dynamic_cast要求基类必须是多态类型,也就是基类中必须有虚函数。因为dynamic_cast是运⾏时通过虚表中存储的type_info判断基类指针指向的是基类对象还是派⽣类对象。

今天的更新就到这里了,如有错误欢迎评论区指出!!