【智能指针二】智能指针互转

【智能指针二】智能指针互转

  • 一、简述
  • 二、static_pointer_cast:静态转换
  • 三、dynamic_pointer_cast:动态转换
  • 四、const_pointer_cast:
  • 五、reinterpret_pointer_cast:

一、简述

智能指针的转换和普通指针的转换是一样的,只是用到的转换函数中间多了一个pointer,

  • 比如普通指针用到的static_cast、dynamic_cast、const_cast和reinterpret_cast。
  • 智能指针用到的与之对应的转换函数为:static_pointer_cast、dynamic_pointer_cast、const_pointer_cast和reinterpret_pointer_cast。
  • 如果你看了智能指针的转换的实现方式,你会发现,他调用的函数也是普通指针的转换函数。
关键字 说明
static_cast 用于良性转换,一般不会导致意外发生,风险很低。
const_cast 用于 const 与非 const、volatile 与非 volatile 之间的转换。
reinterpret_cast 高度危险的转换,这种转换仅仅是对二进制位的重新解释,但是可以实现最灵活的 C++ 类型转换。
dynamic_cast 用于类型安全的向下转型。或者向上转。

C++ static_cast、dynamic_cast、const_cast和reinterpret_cast

二、static_pointer_cast:静态转换

  • 主要讲解下有继承关系的转换(基本类型的本文不涉及)
  • 即可以向上转换(同隐式转换),也可以向下转换
#include <iostream>
#include <memory>
#include<string>
using namespace std;

class Parent;
class Child;

class Parent
{
public:
	Parent() {}  //暂时不明白为何子类需要需要父类的这个默认的构造函数,在此记录,后续研究
	Parent(string name) {
		m_name = name;
	}
	~Parent() {
		cout << "~Parent()" << endl;
	}
public:
	virtual void func()
	{
		cout <<"m_name="<<m_name << ":i am a father." << endl<<endl;
	}
public:
	string m_name;;
};

class Child:public Parent
{
public:
	Child(string name)
	{
		m_name = name;
	}
	~Child() {
		cout << "~Child()" << endl;
	}
public:
	void func()
	{
		cout << "m_name=" << m_name << ":i am a son." << endl<<endl;
	}
public:
	string m_name;
};

int main()
{
	shared_ptr<Parent> father(new Parent("father"));
	shared_ptr<Child> son(new Child("son"));

	// 隐式转换
	shared_ptr<Parent> father1 = son;
	cout << "爸爸1说" << endl;
	father1->func();
	// 向上转
	shared_ptr<Parent> father2 = static_pointer_cast<Parent>(son);
	cout << "爸爸2说" << endl;
	father2->func();
	
	// 向下转
	shared_ptr<Child> son2 = static_pointer_cast<Child>(father);
	cout << "儿子2说" << endl;
	son2->func();
	return 0;
}

输出

在这里插入图片描述

三、dynamic_pointer_cast:动态转换

  • 主要讲解下有继承关系的转换(基本类型的本文不涉及)
  • 即可以向上转换(同隐式转换),
  • 也可以向下转换(可能成功也可能失败,同以下demo中的两个向下转换。和dynamic_cast一样。)如下,
    • 1.把new出的子类指针赋值给父类指针,把此父类指针转换为子类指针,此情况转换正常
    • 2.把new出的父类赋值给父类指针,把此父类指针转换为子类指针,此情况转换失败
  • 避免运行时检查的开销。
#include <iostream>
#include <memory>
#include<string>
using namespace std;

class Parent;
class Child;

class Parent
{
public:
	Parent() {}  //暂时不明白为何子类需要需要父类的这个默认的构造函数,在此记录,后续研究
	Parent(string name) {
		m_name = name;
	}
	~Parent() {
		cout << "~Parent()" << endl;
	}
public:
	virtual void func()
	{
		cout <<"m_name="<<m_name << ":i am a father." << endl<<endl;
	}
public:
	string m_name;;
};

class Child:public Parent
{
public:
	Child() {}
	Child(string name)
	{
		m_name = name;
	}
	~Child() {
		cout << "~Child()" << endl;
	}
public:
	void func()
	{
		cout << "m_name=" << m_name << ":i am a son." << endl<<endl;
	}
public:
	string m_name;
};


int main()
{
	shared_ptr<Parent> father(new Parent("father"));
	shared_ptr<Child> son(new Child("son"));

	// 隐式转换
	shared_ptr<Parent> father1 = son;
	cout << "爸爸1说" << endl;
	father1->func();

	// 向上转
	shared_ptr<Parent> father2 = dynamic_pointer_cast<Parent>(son);
	cout << "爸爸2说" << endl;
	father2->func();

	// 向下转
	shared_ptr<Child> son2 = dynamic_pointer_cast<Child>(father);
	cout << "儿子2说" << endl;
	if (son2)
		son2->func();
	else
		cout << "爸爸转儿子,son2 is null" << endl<<endl;

	// 向下转
	shared_ptr<Parent> father3(new Child("son"));
	shared_ptr<Child> son3 = dynamic_pointer_cast<Child>(father3);
	cout << "儿子3说" << endl;
	if (son3)
		son3->func();
	else
		cout << "爸爸转儿子,son3 is null" << endl << endl;

	return 0;
}

输出

在这里插入图片描述

dynamic_pointer_cast 找不到官方的参考资料,但是可以可以从官方的dymanic_cast资料类推出以上转换规则。参考来自我的上一篇博客,以及cppreference.com/dynamic_cast

四、const_pointer_cast:

  • 同const_cast作用一致,去掉const属性,变成可修改的。
  • 如本文的demo,son的类型是const int类型的智能指针,原本是无法修改的,但是使用const_pointer_cast转换为int,就可以修改了。
  • 网上很多关于const_pointer_cast的例子基本都是错误的,他们使用const_pointer_cast后,还修改原来的int指针,可以说是没有意义的,因为即使没有const_pointer_cast,原来的int指针也是可以修改的。比如https://cplusplus.com/reference/memory/const_pointer_cast/、https://learn.microsoft.com
#include <iostream>
#include <memory>
#include<string>
using namespace std;

int main()
{
	shared_ptr<int> father(new int(10));
	shared_ptr<const int> son(father);

	// 此种情况,son是不可以直接改变值的,
	cout << "儿子son的值" << endl;
	cout << *son<<endl<<endl;
	
	// 但是,const 的son,经过const_pointer_cast转换的son2就可以赋值了。
	shared_ptr<int> son2 = const_pointer_cast<int>(son);
	*son2 = 20;
	cout << "儿子son2赋值后" << endl;
	cout << *son2;

	return 0;
}

输出

在这里插入图片描述

五、reinterpret_pointer_cast:

  • c++17和c++20新增的,目前找不到官方的demo,

  • 具体同reinterpret_cast,区别在于此reinterpret_pointer_cast针对的是智能指针的转换。

  • reinterpret 是“重新解释”的意思,顾名思义,reinterpret_cast 这种转换仅仅是对二进制位的重新解释,不会借助已有的转换规则对数据进行调整,非常简单粗暴,所以风险很高。

  • reinterpret_cast 可以认为是 static_cast 的一种补充,一些 static_cast 不能完成的转换,就可以用 reinterpret_cast 来完成,例如两个具体类型指针之间的转换

  • 简单来说,其他不敢转的,reinterpret_pointer_cast敢转,但是需要遵循场景要求,否则就会出现问题,具体场景参考reinterpret_cast的用法吧,因并reinterpret_pointer_cast没有找到官方的资料和用法。

#include <iostream>
#include <memory>
#include<string>
using namespace std;

class Parent
{
public:
	Parent() {}  //暂时不明白为何子类需要需要父类的这个默认的构造函数,在此记录,后续研究
	Parent(string name) {
		m_name = name;
	}
	~Parent() {
		cout << "~Parent()" << endl;
	}
public:
	virtual void func()
	{
		cout << "m_name=" << m_name << ":i am a father." << endl << endl;
	}
public:
	string m_name;
	int m_age = 30;
};

int main()
{
	std::shared_ptr<std::int8_t[]> p(new std::int8_t[4]{ 1, 1, 1, 1 });
	std::shared_ptr<std::int32_t[]> q = std::reinterpret_pointer_cast<std::int32_t[]>(p);

	std::int32_t r = q[0];
	cout << r<<endl;

	shared_ptr<Parent> father(new Parent("father"));

	// 将 shared_ptr<Parent> 转换为 shared_ptr<int>
	shared_ptr<int> sq=reinterpret_pointer_cast<int>(father);
	cout<<*sq<<endl;


	shared_ptr<char> son(new char[]("father"));
	// 将 shared_ptr<char> 转换为 shared_ptr<int>
	shared_ptr<int> sq2 = reinterpret_pointer_cast<int>(son);
	cout << *sq2<<endl;

	return 0;
}

参考
C++ static_cast、dynamic_cast、const_cast和reinterpret_cast
【cmake实战十】c++从动态库(dll)导出类文章来源地址https://uudwc.com/A/NZ6xk

原文地址:https://blog.csdn.net/junxuezheng/article/details/127374303

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

h
上一篇 2023年08月05日 11:26
快手伸手“供给侧”,找到直播电商的“源头活水”?
下一篇 2023年08月05日 11:32