类型擦除技术我想要掌握类型擦除技术,同时也分享那些,我知道。我希望找到一些有人在他/她最黑暗的时刻想到的疯狂技巧。:)我所知道的第一个也是最明显的,也是最常用的方法是虚函数。只需在基于接口的类层次结构中隐藏类的实现。许多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*
/函数指针式擦除,但包装非常方便。
神不在的星期二
TA贡献1963条经验 获得超6个赞
从根本上说,这些是你的选择:虚函数或函数指针。
如何存储数据并将其与功能相关联可能会有所不同。例如,您可以存储指向基类的指针,并使派生类包含数据和虚函数实现,或者您可以将数据存储在其他位置(例如,在单独分配的缓冲区中),并且只需提供派生类虚函数实现,它void*
指向数据。如果将数据存储在单独的缓冲区中,则可以使用函数指针而不是虚函数。
如果您希望将多个操作应用于类型擦除数据,则即使数据是单独存储的,也可以在此上下文中存储指针到基础。否则,您最终会得到多个函数指针(每个函数指针对应一个类型擦除函数),或者带有指定要执行的操作的参数的函数。
- 3 回答
- 0 关注
- 539 浏览
添加回答
举报
0/150
提交
取消