ご存知のように、これはできません。ただし、同様の効果を可能にするイディオムがあります。
C では、オブジェクト指向設計で "pimpl" イディオムとして知られているものと同様のことを行うことができます。構造体は、構造体のプライベート データとして機能する別の前方宣言された構造体への不透明なポインターを持つことができます。メンバー関数の代わりに構造体を操作する関数は、プライベート メンバーの完全な定義を持つことができ、それを利用できますが、コードの他の部分はできません。例えば:
ヘッダーの foo.h:
struct FooPrivate;
struct Foo {
/* public: */
int x;
double y;
/* private: */
struct FooPrivate* p;
};
extern struct Foo* Foo_Create(); /* "constructor" */
extern void Foo_DoWhatever(struct Foo* foo); /* "member function" */
実装では、foo.c:
struct FooPrivate {
int z;
};
struct Foo* Foo_Create()
{
struct Foo* foo = malloc(sizeof(Foo));
foo->p = malloc(sizeof(FooPrivate));
foo->x = 0;
foo->y = 0;
foo->p->z = 0;
return foo;
}
void Foo_DoWhatever(struct Foo* foo)
{
foo->p->z = 4; /* Can access "private" parts of foo */
}
プログラムで:
#include "foo.h"
int main()
{
struct Foo* foo = Foo_Create();
foo->x = 100; /* Can access "public" parts of foo */
foo->p->z = 20; /* Error! FooPrivate is not fully declared here! */
Foo_DoWhatever(foo); /* Can call "member" function */
return 0;
}
プライベート データにメモリを割り当てるには、「コンストラクタ」関数を使用する必要があることに注意してください。明らかに、プライベート データの割り当てを適切に解除するには、これを特別な「デストラクタ」関数と組み合わせる必要があります。
または、代わりに、構造体にパブリックフィールドをまったく持たないようにしたい場合は、構造体全体を不透明にして、ヘッダーを次のようにすることができます
struct Foo;
extern struct Foo* Foo_Create(); /* "constructor" */
extern void Foo_DoWhatever(struct Foo* foo); /* "member function" */
foo.c での実際の定義struct Foo
、および直接アクセスを提供したい任意のプロパティで使用可能な getter および setter 関数を使用します。