这里可以使用匿名结构。
#ifndef MYSTRUCT_H
#define MYSTRUCT_H
typedef struct {
int i;
struct {
int j;
} MYSTRUCT_PRIVATE;
// NOTE: Avoid putting public members after private
int k;
} MyStruct;
void test_mystruct();
#endif
在应该有权访问私有成员的任何文件中,MYSTRUCT_PRIVATE
在包含此标头之前将其定义为空标记。在这些文件中,私有成员位于匿名结构中,可以使用 访问m.j
,但在所有其他地方,它们只能使用 访问m.MYSTRUCT_PRIVATE.j
。
#define MYSTRUCT_PRIVATE
#include "mystruct.h"
void test_mystruct() {
// Can access .j without MYSTRUCT_PRIVATE in both
// initializer and dot operator.
MyStruct m = { .i = 10, .j = 20, .k = 30 };
m.j = 20;
}
#include <stdio.h>
#include "mystruct.h"
int main() {
// You can declare structs and, if you jump through
// a small hoop, access private members
MyStruct m = { .i = 10, .k = 30 };
m.MYSTRUCT_PRIVATE.j = 20;
// This will not work
//MyStruct m2 = { .i = 10, .j = 20, .k = 30 };
// But this WILL work, be careful
MyStruct m3 = { 10, 20, 30 };
test_mystruct();
return 0;
}
我不建议将公共成员放在私人成员之后。初始化没有成员指示符的结构,例如 with{ 10, 20, 30 }
仍然可以初始化私有成员。如果私有成员的数量发生变化,这也会默默地破坏所有没有成员指示符的初始化程序。最好总是使用成员指示符来避免这种情况。
您必须将结构,尤其是私有成员设计为零初始化,因为在 C++ 中没有自动构造函数。只要将成员初始化为 0,即使没有初始化函数,它们也不会处于无效状态。除非成员指示符初始化,否则初始化为简单的{ 0 }
应该被设计为安全的。
我发现的唯一缺点是这确实会干扰调试器和代码完成之类的东西,当一种类型在一个文件中有一组成员,而在另一个文件中有一组不同的成员时,他们通常不喜欢它。