这个问题不是关于以标准方式引用派生类的基指针。相反,我需要在我的代码中支持两种不同的 IOCTL 结构(SCSI_PASS_THROUGH_DIRECT_EX和SCSI_PASS_THROUGH_DIRECT供参考)。这些结构是封装结构的一部分(每个结构都是独立的)。我已将这些封装结构细分为一个共同的基础。
对于没有使用过 IOCTL 的人来说,处理 IOCTL 需要一个指向该结构的指针。在这种情况下,这是预期的封装结构。
我的问题不在于基指针是否可以指向派生类(我知道它们可以)。我想知道的是,我怎样才能可靠地指向作为这个类层次结构的内存区域中派生类的开始?下面的代码说明了我的策略并在 VS 2010 和 Cygwin (GCC 4.5.3) 中编译。GCC 对 offsetof() 宏的使用不当提出了一些抱怨(从我所阅读的所有内容来看,这似乎可能是真的),但代码似乎反映了我在运行时所追求的。
有没有更好的方法来做到这一点?
#include <iostream>
#include <stdint.h>
#include <cstddef>
enum IoctlType {
T1,
T2
};
struct ptd1 {
uint32_t Version;
uint32_t Size;
uint32_t OffsetOfStuff;
uint8_t ary[1];
};
struct ptd2 {
uint32_t Version;
uint32_t Size;
uint32_t OffsetOfStuff;
uint8_t ary[16];
};
struct base {
IoctlType it;
virtual void* GetPtr()=0;
};
struct derv1 : base {
ptd1 passThrough;
uint8_t ary[15]; // with ptd.ary[1], array is 16 elements
uint32_t fluff; // realign to DWORD boundary
uint32_t stuff;
derv1() {
it = T1;
passThrough.Version = 33;
passThrough.Size = sizeof(ptd1);
passThrough.OffsetOfStuff = offsetof(derv1, stuff);
}
// as the first member of the derv1 struct, this pointer should be the "start"
virtual void* GetPtr() { return &passThrough; }
};
struct derv2 : base {
ptd2 passThrough;
uint32_t stuff;
derv2() {
it = T2;
passThrough.Version = 22;
passThrough.Size = sizeof(ptd2);
passThrough.OffsetOfStuff = offsetof(derv2, stuff);
}
// as the first member of the derv2 struct, this pointer should be the "start"
virtual void* GetPtr() { return &passThrough; }
};
int main() {
base* pBase = new derv1();
std::cout << "Now, check the results" << std::endl;
std::cout << "size of base " << sizeof(base) << std::endl;
std::cout << "size of derv " << sizeof(derv1) << std::endl;
std::cout << "addr of struct " << pBase << std::endl;
std::cout << "addr of passThrough " << pBase->GetPtr() << std::endl;
std::cout << "offset of passThrough " << offsetof(derv1, passThrough)
<< std::endl;
base* pBase2 = new derv2();
std::cout << "Now, check the results" << std::endl;
std::cout << "size of base " << sizeof(base) << std::endl;
std::cout << "size of derv " << sizeof(derv2) << std::endl;
std::cout << "addr of struct " << pBase2 << std::endl;
std::cout << "addr of passThrough " << pBase2->GetPtr() << std::endl;
std::cout << "offset of passThrough " << offsetof(derv2, passThrough)
<< std::endl;
return 0;
}