猿问

类型擦除技术

类型擦除技术

我想要掌握类型擦除技术,同时也分享那些,我知道。我希望找到一些有人在他/她最黑暗的时刻想到的疯狂技巧。:)

我所知道的第一个也是最明显的,也是最常用的方法是虚函数。只需在基于接口的类层次结构中隐藏类的实现。许多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>
杨__羊羊
浏览 540回答 3
3回答

皈依舞

C ++中的所有类型擦除技术都是使用函数指针(用于行为)和void*(用于数据)完成的。“不同”方法在添加语义糖的方式上略有不同。虚函数,例如,只是语义糖struct&nbsp;Class&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;vtable&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;(*dtor)(Class*); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;(*func)(Class*,double); &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;*&nbsp;vtbl};iow:函数指针。也就是说,有一种我特别喜欢的技术:它shared_ptr<void>只是因为它会让那些不知道你可以做到这一点的人感到震惊:你可以将任何数据存储在一个shared_ptr<void>,并且仍然拥有正确的析构函数。结束,因为shared_ptr构造函数是一个函数模板,默认情况下将使用为创建删除函数而传递的实际对象的类型:{ &nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;shared_ptr<void>&nbsp;sp(&nbsp;new&nbsp;A&nbsp;);}&nbsp;//&nbsp;calls&nbsp;A::~A()&nbsp;here当然,这只是通常的void*/函数指针式擦除,但包装非常方便。

神不在的星期二

从根本上说,这些是你的选择:虚函数或函数指针。如何存储数据并将其与功能相关联可能会有所不同。例如,您可以存储指向基类的指针,并使派生类包含数据和虚函数实现,或者您可以将数据存储在其他位置(例如,在单独分配的缓冲区中),并且只需提供派生类虚函数实现,它void*指向数据。如果将数据存储在单独的缓冲区中,则可以使用函数指针而不是虚函数。如果您希望将多个操作应用于类型擦除数据,则即使数据是单独存储的,也可以在此上下文中存储指针到基础。否则,您最终会得到多个函数指针(每个函数指针对应一个类型擦除函数),或者带有指定要执行的操作的参数的函数。
随时随地看视频慕课网APP
我要回答