【发布时间】:2010-08-15 15:39:44
【问题描述】:
我需要一种方法来获取指向 C++ 中对象开头的指针。此对象在模板中使用,因此它可以是任何类型(多态或非多态),并且可能是使用多重继承的对象。
我发现this article 描述了一种在 T 是多态类型的情况下使用 typeid 和 dynamic_cast 到 void* 的方法(参见“动态转换”部分)。
这在 MSVC 上运行得非常好,但是在 GCC (4.x) 上,当它与非多态类型一起使用时,它似乎会失败并吐出编译器错误。
有谁知道以下方法:
- 让 GCC 自行运行,并正确评估 typeid
- 或另一种方法,将在 GCC 上编译
以下是我目前用来尝试实现此目的的代码。
template <typename T>
void* dynamicCastToVoidPtr(T *const ptr)
{
// This is done using a separate function to avoid a compiler error on some
// compilers about non-polymorphic types when calling startOfObject
return dynamic_cast<void*>(ptr);
}
template <typename T>
void* startOfObject(T *const ptr)
{
// In cases of multiple inheritance, a pointer may point to an offset within
// another object
// This code uses a dynamic_cast to a void* to ensure that the pointer value
// is the start of an object and not some offset within an object
void *start = static_cast<void*>(ptr);
if(start)
typeid(start = dynamicCastToVoidPtr(ptr), *ptr);
return start;
}
template <typename T>
void doSomethingWithInstance(T *const instance)
{
// Here is where I need to get a void* to the start of the object
// You can think of this as the deleteInstance function of my memory pool
// where the void* passed into freeMemory should point to the
// start of the memory that the memory pool returned previously
void *start = startOfObject(instance);
if(start)
allocator->freeMemory(start);
}
谢谢。
【问题讨论】:
-
$10/5 states- "[注意:基类子对象的布局 (3.7) 可能与相同类型的最派生对象的布局不同。基类子对象可能具有多态行为 (12.7) 不同于同一类型的最派生对象的多态行为。基类子对象的大小可能为零(第 9 条);但是,具有相同类类型且属于同一类的两个子对象最派生对象不得分配在同一地址 (5.10)。]"
-
struct point { int x; int y; }; point *p = new point(); doSomethingWithInstance(&p->x);会发生什么? -
洛根;那将是对该功能的无效使用。它只能用于已在堆上分配的实例。
-
为什么要这样做?我只是感兴趣——对我来说这听起来很邪恶。
-
@MrD 所以如果我必须知道如何正确使用该函数,那么从 go 一词中传入对象的开头是否如此不合理?请记住,如果我想破坏对象,无论如何我都需要它的“开始”,在对象的“中间”调用析构函数是个坏主意。我认为这里的适当方法是使用分配器的元数据来查找 allocation 的开始,给定指向分配中间的指针,如果你想完全支持这种用法.