接上一主题,C++14中如何设计类似于std::any,使集合在C++中与Python一样支持任意数据?

这篇文章的重点是C++多态的应用,但是如果你是C++新手,

你需要了解以下C++知识:

        构造函数

        拷贝构造函数

        虚拟函数

        纯虚拟函数

        析构函数

类的继承

运算符重写

模板类

        模板参数

数组

        数组的传递

指针与动态内存分配

        

Python:

s = { 3,3,5,9 ,3.14,"神主级","九阳天怒","python"};print(s)

C++:

  

	std::list<int> li = { 1,3,4,5,6,7,8,9 };std::vector<_any> li_any = { "焚心妖莲",1,2,15, _t("逆天邪神"),li ,3.14 };

上面一行代码中,有 char Array[], int, wchar_t  Array[]链表Dobule

下面我们设计一个类 _any,它在构造函数如果是这样,上面语句就能编译过关。

class _any {public:template<class T>_any(const T& tValue) {}
};int main() {      	  std::list<int> li = { 1,3,4,5,6,7,8,9 };std::vector<_any> li_any = { "焚心妖莲",1,2,15, _t("逆天邪神"),li ,3.14 };
}

上面最难的地方是在类_any内部中如何保存 tValue的值,如果把类声明为模板类,很容易解决,但是就要在每_any指定模板参数T,这样行不行?

 用: std::shared_ptr吗?

auto s = std::make_shared<T>(tValue);

也不行,变量声明也要带T的参数。

那应该怎么办了,查了一个资料,最后就是用C++的多态

多态是C++中的一个核心概念,它允许基类的指针或引用调用派生类中定义的方法。多态性通过函数重写和函数重载提供。

看下面代码,你明白了吗?

上在代码还存在一个问题?

上面 “焚心妖莲” 传递的是数组 T = char Array[]  和  T = wchar_t Array[],没关系,改一下就行,在_any再加

个构造函数?

    /// <summary>/// 传递的是数组/// </summary>/// <typeparam name="T"></typeparam>/// <typeparam name="n"></typeparam>/// <param name="arr"></param>/// 创建时间: 2024-11-23      最后一次修改时间:2024-11-23template<typename T, std::size_t n>_any(T(&arr)[n]) : _pData(new _AnyHelper<std::decay_t<T>>(arr,n)){              }

下面给出完整的代码,这代码也是初步的,还有很多要修改之处:

  _any.h

/******************************************************************
文件名				: _any.h作者					: 李锋功能					: std::any手机					: 13828778863Email				:  ruizhilf@139.com创建时间				: 2024年11月23日最后一次修改时间		:  2024年11月23日https://baike.baidu.com/item/deque/849385?fr=ge_ala******************************************************************/
#pragma once
///
#include "__std_in.h"using lf::m;///
__STD_BEGIN_
///
/*
感谢作者:参考: C++ std::any的模拟实现  https://blog.csdn.net/qq_54121864/article/details/136005240class Any
{
private:class AnyHelperBase{public:virtual const std::type_info& Type()const = 0;virtual AnyHelperBase* Clone()const = 0;};template<typename T>class AnyHelper :public AnyHelperBase{public:T data;template<typename ...Args>AnyHelper(Args&&... args) :data(std::forward<Args>(args)...) {}AnyHelper(const AnyHelper& other) :data(other.data) {}AnyHelper(const T& value) :data(value) {}virtual const std::type_info& Type()const{return typeid(T);}virtual AnyHelper* Clone()const{return new AnyHelper(*this);}};template<typename T>friend T AnyCast(const Any& any);template<typename T>friend T AnyCast(Any& any);template<typename T>friend T AnyCast(Any&& any);template<typename T>friend const T* AnyCast(const Any* any);template<typename T>friend T* AnyCast(Any* any);AnyHelperBase* data;
public:Any() :data(nullptr) {}template<typename T>Any(const T& value) : data(new AnyHelper<std::decay_t<T>>(value)) {}Any(const Any& other) :data(other.data->Clone()) {}Any(Any&& other) :data(other.data){other.data = nullptr;}const std::type_info& Type()const{return data->Type();}bool HasValue()const{return data != nullptr;}void Reset(){if (data != nullptr)delete data;data = nullptr;}template<typename T>Any& operator=(const T& value){if (data != nullptr)delete data;data = new AnyHelper<std::decay_t<T>>(value);return *this;}Any& operator=(const Any& other){if (data != nullptr)delete data;data = other.data->Clone();return *this;}Any& operator=(Any&& other){if (data != nullptr)delete data;data = other.data;other.data = nullptr;return *this;}void Swap(Any& other){AnyHelperBase* temp = this->data;this->data = other.data;other.data = temp;}template<typename T, typename ...Args>std::decay_t<T>& Emplace(Args&&... args){if (data != nullptr)delete data;auto temp = new AnyHelper<std::decay_t<T>>(std::forward<Args>(args)...);data = temp;return temp->data;}~Any(){if (data != nullptr)delete data;}
};template<typename T>
T AnyCast(const Any& any)
{auto p = dynamic_cast<Any::AnyHelper<std::decay_t<T>>*>(any.data);if (p == nullptr)throw std::runtime_error("Bad any cast!");return p->data;
}
template<typename T>
T AnyCast(Any& any)
{auto p = dynamic_cast<Any::AnyHelper<std::decay_t<T>>*>(any.data);if (p == nullptr)throw std::runtime_error("Bad any cast!");return p->data;
}
template<typename T>
T AnyCast(Any&& any)
{auto p = dynamic_cast<Any::AnyHelper<std::decay_t<T>>*>(any.data);if (p == nullptr)throw std::runtime_error("Bad any cast!");return p->data;
}
template<typename T>
const T* AnyCast(const Any* any)
{auto p = dynamic_cast<Any::AnyHelper<std::decay_t<T>>*>(any->data);if (p == nullptr)return nullptr;return &p->data;
}
template<typename T>
T* AnyCast(Any* any)
{auto p = dynamic_cast<Any::AnyHelper<std::decay_t<T>>*>(any->data);if (p == nullptr)return nullptr;return &p->data;
}*////
class _any {
public:class _AnyHelperBase{public:virtual const std::type_info& Type()const = 0; // { return typeid(nullptr); }virtual _AnyHelperBase* Clone() const = 0; //{ return nullptr; }virtual bool Equal(const _any& r)const = 0; // { return false; }virtual void* GetDataPointer()const = 0; // return null; }};template<typename T>class _AnyHelper :public _AnyHelperBase{public:/// <summary>/// 用数组来保存T类型数据,如果是单个T类型数据,数据就是 _data[0],/// 否则是 _data.GetDataPointer(),如字符串。/// </summary>lf::_Array<T> _data;public: //-------------------------------构造_AnyHelper(const T* pt, const size_t& nCount) {_data.SetBuffer(nCount + 1);_data.Add(pt, nCount);_data.ZeroBufferAll();}/// <summary>/// 拷贝构造/// </summary>/// <param name="r"></param>_AnyHelper(const _AnyHelper& r) {_data = r._data;}public: //-----------------------------------重写virtual const std::type_info& Type()const override{return typeid(T);}/// <summary>/// 返回一个新的对象指针/// </summary>/// <returns></returns>virtual _AnyHelper* Clone()const override{return new _AnyHelper(*this);}/// <summary>/// 原则:///		相同数据才判断是否相等/// /// </summary>/// <param name="r"></param>/// <returns></returns>/// 创建时间: 2024-11-23      最后一次修改时间:2024-11-23virtual bool Equal(const _any& r)const override{if (Type() == r._pData->Type()) { return  _data == ((_AnyHelper<T>*)r._pData)->_data;} return false;}virtual void* GetDataPointer()const override {if (_data.size() == 0)return nullptr;else if (_data.size() == 1)return &_data[0];elsereturn _data.DataPointer();}public: //-----------------------------------------运算符重载};public: //-------------------------------------------------_any_AnyHelperBase* _pData;   
public:_any() :_pData(nullptr) {};/// <summary>/// 传递的是数组/// </summary>/// <typeparam name="T"></typeparam>/// <typeparam name="n"></typeparam>/// <param name="arr"></param>/// 创建时间: 2024-11-23      最后一次修改时间:2024-11-23template<typename T, std::size_t n>_any(T(&arr)[n]) : _pData(new _AnyHelper<std::decay_t<T>>(arr,n)){              }template<class T>_any(const T& tValue) :_pData(new _AnyHelper<std::decay_t<T>>(&tValue,1)) {}_any(const _any& other) : _pData(other._pData->Clone()) {}~_any() {if (_pData != 0)delete _pData;	 }//-------------------------------------运算符重载bool operator==(const _any& r)const {return _pData->Equal(r);}void* GetDataPointer()const {return _pData->GetDataPointer();}template<class T>const T& ConvertTo() const {const T* pt = (T*)_pData->GetDataPointer();return *pt;}
};//////
__STD_END_
///

下面是例子:

int main() {      	  std::list<int> li = { 1,3,4,5,6,7,8,9 };std::vector<_any> li_any = { "焚心妖莲",1,2,15, _t("逆天邪神"),li ,3.14 };_any ali = li;auto li2 = ali.ConvertTo<std::list<int>>();_pn(li2);  auto f = std::find(li_any.begin(), li_any.end(), li);if (f != li_any.end())std::cout << (*f)._pData->Type().name() << "\n";f = std::find(li_any.begin(), li_any.end(), 3.14);if (f != li_any.end())std::cout << (*f)._pData->Type().name() << "\n";return 0;}

输出结果:

注意:下一步,如何设计 _any类的运算符的 ==  >  <  ,因为要

把_any中用在集合中,或其他std容器中,可以查找,比较。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/61705.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot3与JUnit5集成测试

你可以在 Spring Boot 3 中轻松设置和运行 JUnit 集成测试。合理使用 Spring 提供的注解和工具&#xff0c;可以确保测试的高效性和可靠性。以下是集成测试的步骤和示例&#xff1a; 1. 添加依赖 在 pom.xml 中添加 Spring Boot Starter Test 依赖&#xff0c;它包含 JUnit 5 …

5.STM32之通信接口《精讲》之USART通信---实验串口接收程序

根据上节&#xff0c;我们一已经完成了串口发送程序的代码&#xff0c;并且深入的解析探索了串口的原理&#xff0c;接下来&#xff0c;Whappy小编将带领大家进入串口接收程序的探索与实验&#xff0c;并将结合上一节串口发送一起来完成串口的发送和接收实验。 上来两张图 上图…

微服务即时通讯系统的实现(服务端)----(1)

目录 1. 项目介绍和服务器功能设计2. 基础工具安装3. gflags的安装与使用3.1 gflags的介绍3.2 gflags的安装3.3 gflags的认识3.4 gflags的使用 4. gtest的安装与使用4.1 gtest的介绍4.2 gtest的安装4.3 gtest的使用 5 Spdlog日志组件的安装与使用5.1 Spdlog的介绍5.2 Spdlog的安…

数字IC后端实现时钟树综合系列教程 | Clock Tree,Clock Skew Group之间的区别和联系

Q: Clock&#xff0c;Clock Tree和Skew Group有何区别&#xff1f;Innovus CCOPT引擎是如何使用这些的&#xff1f; Clock是时序约束SDC中的时钟定义点。 create_clock -name clk_osc -period $period_24m [get_ports xin_osc0_func] 时钟树综合(Clock Tree Synthesis)之前应…

tcpdump抓包 wireShark

TCPdump抓包工具介绍 TCPdump&#xff0c;全称dump the traffic on anetwork&#xff0c;是一个运行在linux平台可以根据使用者需求对网络上传输的数据包进行捕获的抓包工具。 tcpdump可以支持的功能: 1、在Linux平台将网络中传输的数据包全部捕获过来进行分析 2、支持网络层…

青少年编程等级考试C++一级,硬币反转问题

代码 #include<iostream>using namespace std;bool a[300];int main(){ int n,m; cin >> n >> m; for(int i 1;i < m;i) { for (int j 1;j < n;j) { if( j % i 0) { a[j] !a[j];…

【Qt流式布局改造支持任意位置插入和删除】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、源代码二、删除代码三、扩展总结 前言 最近在做一个需求需要流式布局&#xff0c;虽然官方example里有一个流式布局范例&#xff0c;但是不能满足我的需求…

“AI玩手机”原理揭秘:大模型驱动的移动端GUI智能体

作者&#xff5c;郭源 前言 在后LLM时代&#xff0c;随着大语言模型和多模态大模型技术的日益成熟&#xff0c;AI技术的实际应用及其社会价值愈发受到重视。AI智能体&#xff08;AI Agent&#xff09;技术通过集成行为规划、记忆存储、工具调用等机制&#xff0c;为大模型装上…

小R的二叉树探险 | 模拟

问题描述 在一个神奇的二叉树中&#xff0c;结构非常独特&#xff1a; 每层的节点值赋值方向是交替的&#xff0c;第一层从左到右&#xff0c;第二层从右到左&#xff0c;以此类推&#xff0c;且该二叉树有无穷多层。 小R对这个二叉树充满了好奇&#xff0c;她想知道&#xf…

Unity类银河战士恶魔城学习总结(P141 Finalising ToolTip优化UI显示)

【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili 教程源地址&#xff1a;https://www.udemy.com/course/2d-rpg-alexdev/ UI部分暂时完结&#xff01;&#xff01;&#xff01; 本章节优化了UI中物品描述的显示效果&#xff0c;技能描述的显示效果 并且可以批…

windows实现VNC连接ubuntu22.04服务器

最近弄了一个700块钱的mini主机&#xff0c;刷了ubuntu22.04系统&#xff0c;然后想要在笔记本上通过VNC连接&#xff0c;这样就有了一个linux的开发环境。最后实现的过程为&#xff1a; 安装vnc服务器 安装 VNC 服务器软件&#xff1a; sudo apt update sudo apt install t…

Perforce《2024游戏技术现状报告》Part3:生成式AI、版本控制、CI/CD等游戏技术的未来趋势与应用

游戏开发者一直处于创新前沿。他们的实践、工具和技术受到各行各业的广泛关注&#xff0c;正在改变着组织进行数字创作的方式。 近期&#xff0c;Perforce发布了《2024游戏技术现状报告》&#xff0c;通过收集来自游戏、媒体与娱乐、汽车和制造业等高增长行业的从业者、管理人…

初阶数据结构之队列的实现

1 队列的定义 什么是队列呢&#xff1f;队列只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作。队列具有先进先出FIFO(First In First Out)的特性。 队头&#xff1a;删除数据的一端称为队头。 队尾&#xff1a;插入数据的一端称为队尾。 2 队列底层结构…

阿里云私服地址

1.解压apache-maven-3.6.1-bin 2.配置本地仓库&#xff1a;修改conf/dettings.xml中的<localReoisitory>为一个指定目录。56行 <localRepository>D:\apache-maven-3.6.1-bin\apache-maven-3.6.1\mvn_repo</localRepository> 3.配置阿里云私服&#xff1a;…

小狐狸AI数字人分身声音克隆形象克隆口播口型同步SAAS系统源码

AI数字人软件系统的未来趋势和用途正朝着多模态交互和智能化方向发展。 1. **多模态交互**&#xff1a;AI数字人技术正在从单一的文本或语音交互&#xff0c;转变为更加自然的多模态交互方式&#xff0c;包括语言对话、行为互动和自主学习能力。这种技术的提升使得数字人能够更…

Idea忽略提交文件、Idea设置文件隐藏、Idea提交时隐藏部分文件、git提交时忽略文件

文章目录 一、在idea中commit文件时隐藏文件方式一&#xff1a;创建.gitignore文件&#xff08;推荐&#xff09;方式二&#xff1a;‌通过File Types设置隐藏文件方式三&#xff1a;通过Git配置忽略文件‌&#xff08;不推荐&#xff09;总结 二、可能遇到的问题2.1、.gitigno…

ARM 架构(Advanced RISC Machine)精简指令集计算机(Reduced Instruction Set Computer)

文章目录 1、ARM 架构ARM 架构的特点ARM 架构的应用ARM 架构的未来发展 2、RISCRISC 的基本概念RISC 的优势RISC 的应用RISC 与 CISC 的对比总结 1、ARM 架构 ARM 架构是一种低功耗、高性能的处理器架构&#xff0c;广泛应用于移动设备、嵌入式系统以及越来越多的服务器和桌面…

如何使用Jest测试你的React组件

在本文中&#xff0c;我们将了解如何使用Jest&#xff08;Facebook 维护的一个测试框架&#xff09;来测试我们的React组件。我们将首先了解如何在纯 JavaScript 函数上使用 Jest&#xff0c;然后再了解它提供的一些开箱即用的功能&#xff0c;这些功能专门用于使测试 React 应…

健康养生点点滴滴

在当下纷扰忙碌的尘世中&#xff0c;养生宛如一支灵动的画笔&#xff0c;精心地为人们勾勒出健康生活的绚丽图景。它绝非仅是对躯体的片面保养&#xff0c;更是对精神世界的深度润泽&#xff0c;一种执着于身心交融、契合无间的生活美学。 饮食养生&#xff0c;仿若画卷中那细…

《TCP/IP网络编程》学习笔记 | Chapter 15:套接字与标准 I/O

《TCP/IP网络编程》学习笔记 | Chapter 15&#xff1a;套接字与标准 I/O 《TCP/IP网络编程》学习笔记 | Chapter 15&#xff1a;套接字与标准 I/O标准 I/O 函数标准 I/O 函数的两个优点标准 I/O 函数和系统函数之间的性能对比标准 I/O 函数的几个缺点 使用标准 I/O 函数利用 fd…