Squ*_*all 2 c c++ encapsulation include header-files
我在文件中有一个类,AType.h
它在AType.cpp中实现.
# include "PrivateType.h"
class AType{
private:
int a, b, c;
PrivateType varX;
public:
...
};
Run Code Online (Sandbox Code Playgroud)
我想在文件中使用类AType main.cpp
,我需要包含AType.h
,但我想避免包含PrivateType.h
在main.cpp中.
我无法varX
用malloc/new 创建.
main.cpp必须在编译时知道AType的大小.
目前的解决方案:(这很糟糕)
1 - 创建要打印的程序sizeof(AType)
.
2 - 更改标题:
# ifdef ATYPE_CPP
# include "PrivateType.h"
#endif
class AType{
private:
# ifdef ATYPE_CPP
int a, b, c;
PrivateType varX;
# else
char data[ the size that was printed ];
# endif
public:
...
};
Run Code Online (Sandbox Code Playgroud)
3 - 而AType.cpp将从以下开始:
# define ATYPE_CPP
# include "AType.h"
Run Code Online (Sandbox Code Playgroud)
编辑1
有没有一种方法或工具可以将复杂的结构自动更改为C基元类型?
我不想打开头文件并找到结构.
如果PrivateType是:
struct DataType {
float a, b;
};
class PrivateType {
void* a;
int b;
short c;
DataType x;
... functions
};
Run Code Online (Sandbox Code Playgroud)
AType将更改为:
class AType {
int a, b, c;
struct x {
void* a;
int b;
short c;
struct x2{
float a, b;
};
};
};
Run Code Online (Sandbox Code Playgroud)
我会分别处理复制/相等方法.
我使用GCC或Clang.
编辑2
一个新的解决方案?
这是GCC.
1 - 获取sizeof(AType)
和__alignof__(AType)
.
2 - 更改标题:
# ifdef ATYPE_CPP
# include "PrivateType.h"
#endif
class AType{
private:
# ifdef ATYPE_CPP
int a, b, c;
PrivateType varX;
# else
char data[ 'the sizeof(AType)' ];
# endif
public:
...
}
# ifdef ATYPE_CPP
;
# else
__attribute__ (( aligned( 'The __alignof__(AType)' ) ));
# endif
Run Code Online (Sandbox Code Playgroud)
3 - 在AType.cpp中写入所有复制/相等方法.
它会起作用吗?
您当前的方法将会巧妙地和灾难性地失败.编译器必须始终看到该类的相同声明.具体来说,考虑编译器生成的类的相等或赋值运算符,AType
而没有正确的PrivateType
present 定义.编译器会错误地为char
数组生成复制/相等方法.
您可以做的是向前声明您的私人类型:
class PrivateType;
class AType{
private:
int a, b, c;
PrivateType *varX;
public:
...
};
Run Code Online (Sandbox Code Playgroud)
请注意,varX
现在是指向尚未定义的类的指针(当然,您必须自己分配/解除分配;智能指针类型可能有帮助).在你的AType.cpp
就可以#include "PrivateType.h"
得到完整的定义,所以你可以实际使用的类的成员.
你不能做你想做的事(因为你排除了动态分配),并且你的"解决方案"一般不起作用,即使你避免了其他人提到的编译器生成的特殊成员函数的问题.一个问题是类型不仅具有大小,而且还具有对齐.例如,您的真实类包含一个int
,但是您的替换类只包含一个char
数组.现在在大多数平台上,int
对齐4(即int
必须位于4字节边界),而char
对齐1(它不能有任何其他对齐而不违反标准).也就是说,一旦你尝试用你的替换定义创建一个对象,你就有可能使它不对齐,这在最好的情况下会导致大幅减速,在最坏的情况下你的程序崩溃(在绝对最坏的情况下) ,它将在您的测试中工作,但在实际使用时失败).