今天给各位分享微乐内蒙麻将开挂免费下载安装的知识,其中也会对微乐内蒙麻将小程序进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!微...
2025-07-26 0
在 C++ 编程中,我们经常会遇到需要编写独立于其操作类型(包括不同函数类型和变量类型)的情况(类似于C语言中的回调函数,但是能适配任意类型)。这时,类型擦除 (Type Erasure) 就派上用场了,它让我们能够以统一的方式处理各种类型。本文将探讨类型擦除的定义、工作原理,并提供实现 std::function 和 std::any 的示例。
类型擦除是一种无需继承或模板即可实现多态性的语言规范。它隐藏了对象的具体类型,只暴露一个统一的接口。这使我们能够通过一个通用接口存储、传递和操作不同类型的对象,而无需在编译时知道具体类型。
类型擦除有几个主要优点:
灵活性:你可以通过一个接口处理不同类型的对象。
解耦:使用类型擦除对象的代码在编译时无需知道具体类型。
多态性:无需继承即可实现运行时的多态性,从而更容易地处理不共享公共基类的现有类型。
实现类型擦除:std::function 和 std::any
C++ 标准库提供了 std::function 和 std::any,它们是类型擦除的示例。一起看看它们的工作原理。
std::function 是一个多功能的可调用对象包装器。它可以存储函数、lambda 表达式或定义了()运算操作符的对象。std::function 的关键特性在于它隐藏了可调用对象的类型,从而统一了调用接口。
示例:
#include <iostream>#include <memory>#include <utility>class CallableBase { //没有类型的接口类public: virtual ~CallableBase() = default; virtual void call() const = 0; //纯虚函数};template <typename T> //用这个子类对接口类重载,赋值具体类型的函数class CallableWrapper : public CallableBase{public: CallableWrapper(T callable) :callable_(std::move(callable)) {} void call() const override { callable_();}private: T callable_;};class SimpleFunction{public:template <typename T> SimpleFunction(T callable): //创建时赋值初始化 callableImpl_(std::make_shared<CallableWrapper<T>>(std::move(callable))) {}void operand() const {//()操作符 if(callableImpl_) callableImpl_->call();}private: std::shared_ptr<CallableBase> callableImpl_; //无类型的接口变量};void helloFunction(){ std::cout <<"Hello, function !!! \n";}int main(){ SimpleFunction f1 = helloFunction; SimpleFunction f2 = [](){std::cout << "Hello, Lambda !!!\n";}; f1(); //输出:Hello, Function !!! f2(); //输出:Hello, Lambda !!! return 0;}
在此例中,SimpleFunction 用于存储常规函数和lambda 表达式。被调用函数的实际类型被擦除了,并且 SimpleFunction 提供了一种统一的方法来调用存储的函数。
std::any 是一个类型安全的容器,可容纳任何类型的单个值。它可以存储任何类型的对象,并且可以使用类型安全的强制类型转换来检索存储的值。
#include <iostream>#include <memory>#include <utility>#include <typeinfo>#include <typeindex>class AnyBase{public: virtual ~AnyBase() = default; virtual std::type_index type() const = 0; virtual std::unique_ptr<AnyBase> clone() = 0;};template <typename T>class AnyWrapper : public AnyBase{public: explicit AnyWrapper(T value) : value_(std::move(value)){} std::type_index type() const override { //存储了类型信息,类型转换时用 return typeid(T); } std::unique_ptr<AnyBase> clone() override{ return std::make_unique<AnyWrapper<T>>(value_); } T& get(){ return value_; } private: T value_;};class SimpleAny{public: SimpleAny() = default; template <typename T> SimpleAny(T value) : value_(std::make_unique<AnyWrapper<T>>(std::move(value))){} SimpleAny(const SimpleAny& other) : value_(other.value_ ? other.value_->clone() : nullptr){} SimpleAny& operator=(const SimpleAny& other) { if (this != &other) { value_ = other.value_ ? other.value_->clone() : nullptr; } return *this; } std::type_index type() const{ return value_ ? value_->type() : typeid(void); } template <typename T> T& get(){ if (type() != typeid(T)) { //类型转换时判断是否类型匹配 throw std::bad_cast(); } return static_cast<AnyWrapper<T>*>(value_.get())->get(); }private: std::unique_ptr<AnyBase> value_;};int main(){ SimpleAny a(10); std::cout << "Stored int: " << a.get<int>() << "\n"; a = std::string("Hello, Any!"); std::cout << "Stored string: " << a.get<std::string>() << "\n"; return 0;}
本例中,“SimpleAny”用于存储一个 int 类型,然后存储一个 std::string 类型。
相关文章
今天给各位分享微乐内蒙麻将开挂免费下载安装的知识,其中也会对微乐内蒙麻将小程序进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!微...
2025-07-26 0
有一种交锋,没有声音,却比任何炮火都响亮。在青岛港,一个本该平常的迎接,变成了一场关于规矩的无声对峙。几十年后,访问的美国人仍在回忆那一天。红毯被突然...
2025-07-26 0
当陈佩斯饰演的军阀拎着手枪闯进京剧后台,张口却蹦出"斯坦尼斯拉夫斯基"时,观众席爆发的笑声几乎掀翻屋顶。这幕经典场景如今被4K摄影机搬上大银幕——舞台...
2025-07-26 0
文 | 略大参考,作者 | 杨知潮2010年,苹果在iPhone4上首次搭载了自己A系列自研芯片。核心处理器SOC是人类制造业皇冠上的明珠,能够设计S...
2025-07-26 0
冯德莱恩这趟北京之行只有短短一天,可她临走前说的那句话,却让特朗普政府坐不住了。这位欧盟委员会主席在机场对记者说:欧盟和中国加强贸易往来,跟美欧关系好...
2025-07-26 0
民进党当局和绿媒疯狂炒作“抢夺贺电”,向来标榜“维持现状”的国民党,这回居然也跟着站在站在绿营那边,好在中国学生体育联合会发布情况说明,并坚决表示反对...
2025-07-26 0
7月24日,上海玄合元门诊部与浦东康桥“院士之家”举行战略合作签约仪式,正式成为其官方指定医疗保障单位。此次合作将为入驻“院士之家”的两院院士及科研领...
2025-07-26 0
宁夏一男子偷拍跟情人在出租屋发生性关系时,偷偷拍下不雅视频,并以此向情人勒索3万元,情人随后报警。不仅如此,该男子还曾以类似手段向一对夫妇勒索6.6万...
2025-07-26 0
发表评论