用C++自写的Any

     相信大家都很熟悉JAVA的Object类,或多少也知道boost里的any吧,而小编不才写了个类似的玩意出来,下面我来说下这个玩意有啥不同和特别之处及实现的原理。

    首先展示Any类型功能:

 

 

1.首先肯定是一个Any对象哈,(注意:这个Any不是boost库的,这是作者写的哈)

 

2.其次直接给它赋值一个字符串s,拿出来的时候用泛型转换后得到该字符串并输出哈

3.有趣的是它也可以把自己直接拷贝给别人(代码:string b =s),看图输出结果跟最开始给s赋的值相同

4.s =ceshi(55),看到这行不难发现这个Any定义出来的对象是可以被赋值任何对象的,输出结果如图所示

5.赐予vector向量Any类型,向量插入数据的时候一样可以随便插入各种类型数据

6.其次它的底层数据是使用智能指针unique_ptr实现,所以它可以在给该变量赋值为空的时候自动释放被存到里面new出的空间

下面是基于Any封装的AnyMap键值容器:

其实跟把Any放在vector里原理一样都是可放随意类型,而说到这里肯定会有个疑问,竟然可以把Any放在vector里面,为啥不一样使用Map,其实这个跟上面说的自动释放内存一样,这里当你删除一个元素的时候如果该元素是new出来的空间也会自动清楚。

实现原理:

在数字1这里就是初始化不用讲啦,数字2这里就是根据=号左边的类型来获取是否有该值,没有返回nullptr,数字3是从数据里获取到指向无类型的数据,经过在数字2那一步指定类型的转换返回出去,而这时读者肯定会有个疑问Any为什么可以不需要指定类型可以随便赋值各种类型数据,其实这就是接下来讲的重点。这个类里边核心变量数据m_data,也就它一个,它是关键。

 

m_data数据的类

abstacatData有个嵌入类AnyDate,而AnyDate又继承于abstacatData,从这个嵌入类可以看出这是一个普通的模板类,再回来我们的Any类,它也继承abstacatData这个父类,所以AnyDate就有操作AnyDate的权限,根据我们Any类里给m_date赋值看出是new了一个AnyDate对象并根据模板类型存储数据,而我们m_date是abstacatData类型,是AnyDate的父类,而基类只是一个普通的类,所以可以直接保存创建的AnyDate对象的地址,在Any内部赋值的时候是AnyDate需要泛型,而abstacatData不需要泛型,所以就实现了创建Any对象时不用写指定类型。AnyMap原理与其一样,只是在外面利用Map再次帮装了一遍就不贴出来了哈。

      新人一枚,第一次发表博客,写的不好忘请见解哈哈!!

点击下载:源码链接

`std::any` 是 C++17 中引入的一个新特性,用于存储任意类型的值,因此如果你要使用 `std::any`,你需要使用 C++17 或更高版本的编译器。 如果你的编译器不支持 C++17,你可以使用其他的实现方式,例如使用模板来实现类似的功能。比如下面这个示例: ```cpp #include <iostream> #include <string> #include <typeindex> #include <unordered_map> #include <stdexcept> class Any { public: Any() : m_tpIndex(std::type_index(typeid(void))) {} Any(const Any& other) : m_ptr(other.Clone()), m_tpIndex(other.m_tpIndex) {} Any(Any&& other) : m_ptr(std::move(other.m_ptr)), m_tpIndex(other.m_tpIndex) {} template<typename T, typename = typename std::enable_if<!std::is_same<typename std::decay<T>::type, Any>::value, T>::type> Any(T&& value) : m_ptr(new Derived<typename std::decay<T>::type>(std::forward<T>(value))), m_tpIndex(typeid(typename std::decay<T>::type)) {} bool IsNull() const { return !bool(m_ptr); } template<class T> bool Is() const { return m_tpIndex == std::type_index(typeid(T)); } template<class T> typename std::decay<T>::type& AnyCast() { if (!Is<T>()) { throw std::runtime_error("can not cast " + std::string(m_tpIndex.name()) + " to " + std::string(typeid(T).name())); } auto derived = dynamic_cast<Derived<typename std::decay<T>::type>*>(m_ptr.get()); return derived->m_value; } Any& operator = (const Any& other) { if (m_ptr == other.m_ptr) { return *this; } m_ptr = other.Clone(); m_tpIndex = other.m_tpIndex; return *this; } private: struct Base { virtual ~Base() {} virtual std::unique_ptr<Base> Clone() const = 0; }; template<typename T> struct Derived : Base { template<typename U> Derived(U&& value) : m_value(std::forward<U>(value)) { } std::unique_ptr<Base> Clone() const { return std::unique_ptr<Base>(new Derived<T>(m_value)); } T m_value; }; private: std::unique_ptr<Base> Clone() const { if (m_ptr != nullptr) { return m_ptr->Clone(); } return nullptr; } std::unique_ptr<Base> m_ptr; std::type_index m_tpIndex; }; int main() { Any a = 1; std::cout << a.AnyCast<int>() << std::endl; a = std::string("hello"); std::cout << a.AnyCast<std::string>() << std::endl; try { a.AnyCast<int>(); } catch (const std::exception& e) { std::cout << e.what() << std::endl; } return 0; } ``` 这段代码定义了一个 `Any` 类,使用模板参数来存储任意类型的值,并在运行时动态判断类型。你可以像使用 `std::any` 一样使用 `Any` 类型的变量,例如调用 `AnyCast` 方法来获取存储的值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IChessChess

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值