如何"取消包含"头文件?

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中写入所有复制/相等方法.

它会起作用吗?

Gre*_*ill 6

您当前的方法将会巧妙地和灾难性地失败.编译器必须始终看到该类的相同声明.具体来说,考虑编译器生成的类的相等或赋值运算符,AType而没有正确的PrivateTypepresent 定义.编译器会错误地为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"得到完整的定义,所以你可以实际使用的类的成员.


cel*_*chk 5

你不能做你想做的事(因为你排除了动态分配),并且你的"解决方案"一般不起作用,即使你避免了其他人提到的编译器生成的特殊成员函数的问题.一个问题是类型不仅具有大小,而且还具有对齐.例如,您的真实类包含一个int,但是您的替换类只包含一个char数组.现在在大多数平台上,int对齐4(即int必须位于4字节边界),而char对齐1(它不能有任何其他对齐而不违反标准).也就是说,一旦你尝试用你的替换定义创建一个对象,你就有可能使它不对齐,这在最好的情况下会导致大幅减速,在最坏的情况下你的程序崩溃(在绝对最坏的情况下) ,它将在您的测试中工作,但在实际使用时失败).