为了账号安全,请及时绑定邮箱和手机立即绑定

类型擦除技术

类型擦除技术

C++ C
杨__羊羊 2019-07-25 19:31:40
类型擦除技术我想要掌握类型擦除技术,同时也分享那些,我知道。我希望找到一些有人在他/她最黑暗的时刻想到的疯狂技巧。:)我所知道的第一个也是最明显的,也是最常用的方法是虚函数。只需在基于接口的类层次结构中隐藏类的实现。许多Boost库都这样做,例如Boost.Any这样做是为了隐藏你的类型,而Boost.Shared_ptr这样做是为了隐藏(de)分配机制。然后有一个函数指针指向模板化函数的选项,同时将实际对象保存在void*指针中,如Boost.Function确实隐藏了仿函数的实际类型。可以在问题的最后找到示例实现。所以,对于我的实际问题:你知道其他什么类型的擦除技术?如果可能的话,请提供示例代码,用例,您对它们的体验以及可能的进一步阅读链接。编辑(因为我不确定是否将此作为答案添加,或者只是编辑问题,我只会做更安全的问题。)另一个很好的技术来隐藏没有虚函数或void*摆弄的东西的实际类型,是一个GMan在这里工作,与我的问题有关,这个问题究竟是如何运作的。示例代码:#include <iostream>#include <string>// NOTE: The class name indicates the underlying type erasure technique// this behaves like the Boost.Any type w.r.t. implementation detailsclass Any_Virtual{         struct holder_base{                 virtual ~holder_base(){}                 virtual holder_base* clone() const = 0;         };         template<class T>         struct holder : holder_base{                 holder()                         : held_()                 {}                 holder(T const& t)                         : held_(t)                 {}                 virtual ~holder(){                 }                 virtual holder_base* clone() const {                         return new holder<T>(*this);                 }                 T held_;         };public:         Any_Virtual()                 : storage_(0)         {}         Any_Virtual(Any_Virtual const& other)                 : storage_(other.storage_->clone())         {}         template<class T>         Any_Virtual(T const& t)                 : storage_(new holder<T>(t))         {}         ~Any_Virtual(){                 Clear();         }         Any_Virtual& operator=(Any_Virtual const& other){                 Clear();                 storage_ = other.storage_->clone();                 return *this;         }         template<class T>         Any_Virtual& operator=(T const& t){                 Clear();                 storage_ = new holder<T>(t);                 return *this;         }         void Clear(){                 if(storage_)                         delete storage_;         }         template<class T>
查看完整描述

3 回答

?
皈依舞

TA贡献1851条经验 获得超3个赞

C ++中的所有类型擦除技术都是使用函数指针(用于行为)和void*(用于数据)完成的。“不同”方法在添加语义糖的方式上略有不同。虚函数,例如,只是语义糖

struct Class {
    struct vtable {
        void (*dtor)(Class*);
        void (*func)(Class*,double);
    } * vtbl};

iow:函数指针。

也就是说,有一种我特别喜欢的技术:它shared_ptr<void>只是因为它会让那些不知道你可以做到这一点的人感到震惊:你可以将任何数据存储在一个shared_ptr<void>,并且仍然拥有正确的析构函数。结束,因为shared_ptr构造函数是一个函数模板,默认情况下将使用为创建删除函数而传递的实际对象的类型:

{
    const shared_ptr<void> sp( new A );} // calls A::~A() here

当然,这只是通常的void*/函数指针式擦除,但包装非常方便。


查看完整回答
反对 回复 2019-07-25
?
神不在的星期二

TA贡献1963条经验 获得超6个赞

从根本上说,这些是你的选择:虚函数或函数指针。

如何存储数据并将其与功能相关联可能会有所不同。例如,您可以存储指向基类的指针,并使派生类包含数据虚函数实现,或者您可以将数据存储在其他位置(例如,在单独分配的缓冲区中),并且只需提供派生类虚函数实现,它void*指向数据。如果将数据存储在单独的缓冲区中,则可以使用函数指针而不是虚函数。

如果您希望将多个操作应用于类型擦除数据,则即使数据是单独存储的,也可以在此上下文中存储指针到基础。否则,您最终会得到多个函数指针(每个函数指针对应一个类型擦除函数),或者带有指定要执行的操作的参数的函数。


查看完整回答
反对 回复 2019-07-25
  • 3 回答
  • 0 关注
  • 539 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信