获取没有对象的类的 vtable
Obtain the vtable of a class without an object
我正在尝试实现一个类似于这里描述的第一个系统。也就是说,(滥用)使用 vtable 修改在运行时更改对象行为。这是我尝试在我正在处理的C++项目中创建一个高效的类型泛型包装器的一部分。
如果您无法访问它,该示例将使用 memcpy()
和 this
指针复制 vtable,如下所示:
void setType( const DataType& newType )
{
memcpy( this, &newType, sizeof(DataType) );
}
但是,我对此方法有一个问题:我没有要从中复制 vtable 的目标类的对象,并且不想创建一个,因为某些类型的构造成本很高。
有没有办法访问 vtable,该 vtable 将被放置在给定类的对象中,而没有该类的对象?
如果它有点可移植性会更好,但我在很大程度上已经接受了这是特定于编译器的;因此,如果没有其他选择,仅GCC/G ++方法是可以接受的。让我们也假设我只关心在相当标准的操作系统和架构上构建它。
我正在使用 C++11,如果这在某种程度上有所帮助。
编辑:我想完全清楚,我知道这种行为有多危险。我对这个想法更感兴趣,也许它在非常受控的情况下的狭隘应用,而不是我对它是生产软件的好主意更感兴趣,尽管我的介绍可能会暗示。
struct many_vtable {
void(*dtor)(void*);
void(*print)(void const*,std::ostream&);
};
template<class T>struct tag_t{};
template<class T>constexpr tag_t<T> tag = {};
template<class T>
many_vtable const* make_many_vtable(tag_t<T>){
static const many_vtable retval = {
// dtor
[](void* p){
reinterpret_cast<T*>(p)->~T();
},
// print
[](void const*p, std::ostream& os){
os<<*reinterpret_cast<T const*>(p);
}
};
return &retval;
}
struct many {
many_vtable const* vtable=nullptr;
std::aligned_storage_t<100, alignof(double)> buff;
void clear(){if(vtable) vtable->dtor(&buff);vtable=nullptr;}
~many(){ clear(); }
many()=default;
many(many const&)=delete; // not yet supported
many& operator=(many const&)=delete; // not yet supported
explicit operator bool()const{return vtable!=nullptr;}
template<class T,class...Args>
void emplace(Args&&...args){
static_assert(alignof(T) <= alignof(double), "not enough alignment");
static_assert(sizeof(T) <= 100, "not enough size");
clear();
::new((void*)&buff) T(std::forward<Args>(args)...);
vtable=make_many_vtable(tag<T>);
}
friend std::ostream& operator<<(std::ostream& os, many const&m){
if(!m.vtable) return os;
m.vtable->print(&m.buff, os);
return os;
}
};
这是一个手动的 vtable 设计。 它可以存储最多 100 个字节的任何内容,其对齐方式小于可以打印到流的双倍。
"擦除"到更多(或不同)操作很容易。 例如,能够复制/移动到另一个多个。
它不违反标准,并且与链接示例具有类似的开销。
many m;
m.emplace<int>(3);
std::cout << m << 'n';
m.emplace<double>(3.14);
std::cout << m << 'n';
活生生的例子。
这是手动 vtables,因为我们基本上是手动重新实现 vtable 概念。
相关文章:
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- CMake-按正确顺序将项目与C运行时对象文件链接
- 空基优化子对象的地址
- 将对象数组的引用传递给函数
- 你能重载对象变量名本身返回的内容吗
- C++使用整数的压缩数组初始化对象
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 将对象移动到std::shared_ptr
- 代理对象的常量正确性
- 提升 ASIO 无法识别计时器对象
- 将Ref对象作为类成员
- 编译器是否会创建vtable,而不考虑在c++中创建对象
- 对"车辆的 vtable"的未定义引用 - 面向对象的编程练习
- 从 base 转换的派生对象是否需要使用 vtable
- 我实际上是在调用 ctor 并在指向对象的指针上初始化 vtable 吗?C++
- 带/不带 vtable 的对象初始化
- 获取没有对象的类的 vtable
- 什么是 vtable 锚定,以及它在共享对象中的工作原理
- 是否可以将对象向下转换为在C++中不定义额外变量或vtable的子类