一.C语言中的类型转换

1.内置类型之间的转换

// a、内置类型之间
// 1、隐式类型转换    整形之间/整形和浮点数之间
// 2、显示类型的转换  指针和整形、指针之间



int main()
{
	int i = 1;
	// 隐式类型转换
	double d = i;
	printf("%d, %.2f\n", i, d);

	int* p = &i;
	// 显示的强制类型转换
	int address = (int)p;
	printf("%p, %d\n", p, address);

	return 0;
}

2.内置类型和自定义类型之间

// b、内置类型和自定义类型之间
// 1、自定义类型 = 内置类型  ->构造函数支持
// 2、内置类型 = 自定义类型
class A
{
public:
	//explicit A(int a)
	A(int a)
		:_a1(a)
		,_a2(a)
	{}

	A(int a1, int a2)
		:_a1(a1)
		, _a2(a2)
	{}

	// ()被仿函数占用了,不能用
	// operator 类型实现,无返回类型
	//explicit operator int()
	operator int()
	{
		return _a1 + _a2;
	}
private:
	int _a1 = 1;
	int _a2 = 1;
};
int main()
{
	string s1 = "1111111";
	A aa1 = 1;
	//A aa1 = (A)1;
	A aa2 = { 2,2 };
	const A& aa3 = { 2,2 };

	int z = aa1.operator int();
	//int x = (int)aa1;
	int x = aa1;
	int y = aa2;
	cout << x << endl;
	cout << y << endl;

	std::shared_ptr<int> foo;
	std::shared_ptr<int> 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";

	return 0;
}

我们加了explicit,表示不能进行隐式类型转换,但是还是支持强制类型转换

内置类型   -->   自定义类型,要通过构造函数进行实现

3.自定义类型和自定义类型之间 -- 对应的构造函数支持

// c、自定义类型和自定义类型之间 -- 对应的构造函数支持
class A
{
public:
	A(int a)
		:_a1(a)
		, _a2(a)
	{}

	A(int a1, int a2)
		:_a1(a1)
		, _a2(a2)
	{}

	int get() const
	{
		return _a1 + _a2;
	}
private:
	int _a1 = 1;
	int _a2 = 1;
};

class B
{
public:
	B(int b)
		:_b1(b)
	{}

private:
	int _b1 = 1;
};


int main()
{
	A aa1(1);
	B bb1(2);
    aa1 = (B)aa2;
    return 0;
}

目前是转不了的,因为没有任何的关联,但是,我们可以加一个构造函数

// c、自定义类型和自定义类型之间 -- 对应的构造函数支持
class A
{
public:
	A(int a)
		:_a1(a)
		, _a2(a)
	{}

	A(int a1, int a2)
		:_a1(a1)
		, _a2(a2)
	{}

	int get() const
	{
		return _a1 + _a2;
	}
private:
	int _a1 = 1;
	int _a2 = 1;
};

class B
{
public:
	B(int b)
		:_b1(b)
	{}

	B(const A& aa)
		:_b1(aa.get())
	{}

private:
	int _b1 = 1;
};


int main()
{
	A aa1(1);
	B bb1(2);

	bb1 = aa1;
}

这样就行了

这里不是权限的缩小和放大,这里是类型转换

二.为什么C++需要四种类型转换

三. C++强制类型转换

1.static_cast

int main()
{
	// 对应隐式类型转换 -- 数据的意义没有改变
	double d = 12.34;
	int a = static_cast<int>(d);
	cout << a << endl;
    return 0;
}

2.reinterpret_cast

int main()
{
	// 对应隐式类型转换 -- 数据的意义没有改变
	double d = 12.34;
	int a = static_cast<int>(d);
	cout << a << endl;
	
	// 对应强制类型转换 -- 数据的意义已经发生改变
	int* p1 = reinterpret_cast<int*>(a);
}

3.const_cast

但是const_cast,是有对应得风险的

编译器会将const值直接替换成常量,或者是放入寄存器中,改了我们也读不到(监视窗口看都是3)

4.dynamic_cast


class A
{
public:
	//virtual void f() {}

	int _a = 1;
};

class B : public A
{
public:
	int _b = 2;
};

void fun(A* pa)
{
	// dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回
	// 指向父类转换时有风险的,后续访问存在越界访问的风险
	// 指向子类转换时安全
	B* pb1 = (B*)pa;
	cout << "pb1:" << pb1 <<endl;
	cout << pb1->_a << endl;
	cout << pb1->_b << endl;
	pb1->_a++;
	pb1->_b++;
	cout << pb1->_a << endl;
	cout << pb1->_b << endl;
}



int main()
{
	A a;
	B b;
	fun(&a);
	fun(&b);

	return 0;
}
class A
{
public:
	virtual void f() {}

	int _a = 1;
};

class B : public A
{
public:
	int _b = 2;
};

void fun(A* pa)
{
	// dynamic_cast会先检查是否能转换成功(指向子类对象),能成功则转换,
	// (指向父类对象)不能则返回NULL
	B* pb1 = dynamic_cast<B*>(pa);
	if (pb1)
	{
		cout << "pb1:" << pb1 << endl;
		cout << pb1->_a << endl;
		cout << pb1->_b << endl;
		pb1->_a++;
		pb1->_b++;
		cout << pb1->_a << endl;
		cout << pb1->_b << endl;
	}
	else
	{
		cout << "转换失败" << endl;
	}
}

int main()
{
	A a;
	B b;
	// fun(&a);
	fun(&b);

	return 0;
}

使用dynamic_cast的时候要进行转换,那么就必须要实现多态(要检查虚表里面的标识)

本质上dynamic_cast就是去检查该标识,就是来识别是父类还是子类

四. RTTI(了解)

五. 常见面试题

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐