指向类层次结构的派生部分的指针
Pointer to derived portion of a class hierarchy
这个问题不是关于以标准方式引用派生类的基本指针。 相反,我需要在我的代码中支持两种不同的 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;
}
经过多次内部辩论,我决定斯拉瓦的评论是最有帮助的; 不要这样做。 为此,我基本上制作了一个包装器结构,它知道要使用哪种结构。 标准是:
- 这是 Windows 7 及更早版本,还是 Windows 8 及更高版本
- 如果是 Windows 8 及更高版本,这是 32 位操作系统上的 64 位进程吗
然后,有适当的函数用于获取/设置所需的值。 最终产品如下所示:
struct ScsiPassThruExWBuffers {
SCSI_PASS_THROUGH_DIRECT_EX passThru;
unsigned char cdbExt[259]; // 260 by SCSI Standard
int fluff; // realign
unsigned char senseInfo[256];
STOR_ADDR_BTL8 addrInfo;
};
struct ScsiPassThru32ExWBuffers {
SCSI_PASS_THROUGH_DIRECT32_EX passThru;
unsigned char cdbExt[259]; // 260 by SCSI Standard
int fluff; // realign
unsigned char senseInfo[256];
STOR_ADDR_BTL8 addrInfo;
};
struct ScsiPassThruWBuffers {
SCSI_PASS_THROUGH_DIRECT passThru;
unsigned char senseInfo[256];
};
enum PassThruType {
PassThru,
PassThruEx,
PassThru32Ex
};
struct Wrapper {
void * pStruct;
PassThruType ptt;
unsigned int ioctlCode;
unsigned int aggregateStructSize;
// ctors/dtors
Wrapper();
Wrapper(Wrapper const& source); // copy c-tor
~Wrapper(); // delete memory allocated for pStruct;
// several setters/getters for the properties in the structures
private:
Wrapper& operator=(Wrapper const& rhs); // no implementation
};
这使得直通结构的所有聚合或封装结构都保留为 POD,并且可靠地确定偏移量的能力是合理的。
相关文章:
- 从纯虚拟类 (A) 派生的指针无法访问来自纯类 (B) 的重载方法
- C++函数解析基类指针到派生类指针
- 在将派生类指针类型转换为派生类指针后,从基类指针调用派生类函数
- 我们可以在不知道其真实类型的情况下将基类指针转换为派生类指针吗?
- 与简单地创建派生类指针相比,将基类绑定到派生类有什么优点?
- 将基本实例指针强制转换为派生实例指针是否合法?(实例不是派生实例)
- 有没有办法复制派生类指针的向量而不将其强制转换为基类?
- 使用 boost::序列化将派生类指针序列化为向量时出现问题
- 检查指针是否是带有变异模板的派生的指针
- 将基类指针转换为未知派生类指针
- 返回返回基本或派生CLSS指针的功能值
- 通过引用将派生类指针传递给需要基指针的函数
- 从基类指针到派生类指针的static_cast无效
- 从派生的指针中调用虚拟功能,而无需支付VTable价格
- C++ 多态行为:交换派生的指针类型
- 将派生类指针的向量传递给线程
- 派生类指针指向的函数
- 在 C++ 中将派生类指针分配给基类指针
- 描述为什么不允许在C++中将基类指针转换为派生类指针
- 将派生类指针强制转换为基类引用