考虑到您有两个类,Base和Derived,Derived是从Base公开继承的。
#include <iostream>
struct Base {
public:
unsigned char a;
int b;
Base() : a('a'), b (2) { };
unsigned char get_a() {
return a;
}
int get_b() {
return b;
}
} __attribute__ ((__packed__)) ;
struct __attribute__ ((__packed__)) Derived : public Base {
public:
unsigned char c;
int d;
Derived() : c('c'), d(4) { };
unsigned char get_c() {
return c;
}
int get_d() {
return d;
}
};
Run Code Online (Sandbox Code Playgroud)
我正在做一些实验,这些是发现/问题。
首先,您不能在继承链中仅打包一个类。您必须打包链中的所有东西,否则就什么也没有。
其次,打包后,两个类的内存彼此相邻。首先是Base的内存,然后是Derived的内存。例如,Derived的内存布局将是:Base的5个字节,然后Derived的下5个字节。是肯定/正确的吗?
第三,这与我的工作和IMO一个有趣的问题有关。在我的流程中,直到确定的一点,我需要使用基类指针,并且在该特定指针之后,可以通过执行mem_copy或其他操作将所有基类指针转换为派生类指针。当然,我会添加“派生成员”的必要值。我怎样才能做到这一点?
要解决第三个问题,您将建议什么方法?如果没有虚拟,则由于虚拟会向内存增加4/8字节。
首先,当您谈论编译器扩展时,所有这些都是高度特定于编译器的。
gcc__attribute__ ((__packed__))将对齐设置为 1 并删除填充。这意味着 sizeof(Base) 通常应为 5,而 Derived 按照您的建议添加另外 5 个字节(假设 sizeof(int) == 4)。这就是 pack 在 gcc 和相关编译器(如 clang)中的工作原理。使用不同的编译器,一切都会失败。
至于转换指针,您应该有一个 Derived 的构造函数,它接受一个const Base &参数。编译器应该为此生成正确的 memcpy() 。
总的来说,您应该有充分的理由使用打包,因为对打包结构进行操作会产生效率极低的代码。