2016-02-09 15 views
7

私はCプログラムを作成し、gcc 4.4.6を使用してコンパイルしています。私はC++コンパイラを使いたくありません。Cプログラミングのデカップリングインターフェイスから構造体前方宣言を使用して

私はコンポーネントを実装していますが、私はこのコンポーネントのいくつかのインスタンスを実行時にほかのコンポーネントが所有し、所有しています。

インターフェイスの定義を実装から切り離し、その実装で使用する内部構造とデータ型を隠す手段として、前方構造宣言を使用するように見えました。

インタフェースファイル:component.h

struct _hidden_implementation_type; 
typedef struct _hidden_implementation_type visible_type_to_clients; 

int component_function1(visible_type_to_clients instance); 

実装ファイル:component.c

struct _hidden_implementation_type 
{ 
    int foo; 
}; 

クライアントファイル:main.cの

int main(int argc, char** argv) 
{ 
    visible_type_to_clients a; 
    return component_function1(a); 
} 

この作品を作成するにはどうすればよいですか?それ以外の方法として、複数のコンポーネントのインスタンス化を許可し、パブリックインターフェイスと実装の間のデカップリングを提供する方法はありますか?

+2

通常のアプローチは、構造の内部の詳細がクライアントに表示されていないタイプを構成する*ポインタ*を含む:

ここで比較のために2つの実装です。 –

+0

'instance_type'はインスタンスであり、型ではありません。 – Olaf

+0

それはタイプミスでした。 – Rire1979

答えて

6

あなたはほぼあります。それはしかし、有益な何もしません - これは、少なくともコンパイルします

int main(void) 
{ 
    visible_type_to_clients *a = 0; 
    return component_function1(a); 
} 

struct hidden_implementation_type; 
typedef struct hidden_implementation_type visible_type_to_clients; 

int component_function1(visible_type_to_clients *instance_type); 

と:あなたのインターフェイスは、不透明なタイプへのポインタの面でなければなりません。型の値を作成し、ポインタを返し、その後、あなたが使用することができますし

visible_type_to_clients *new_visible(void); 

:あなたはおそらくのような機能を必要とするだろう

int main(void) 
{ 
    visible_type_to_clients *a = new_visible(); 
    return component_function1(a); 
} 

基本的には、クライアントはしませんコンパイラにその型の大きさを伝えていないので、型のスタック(またはグローバル構造)上に構造を作成できるようにしてください。しかし、あなたはポインタを扱うことができます - そしてタイプされたポインタは、 'タイプなしの' void *ポインタよりもはるかに安全です。

私は簡単にエラーチェックをしませんでした。すべての実用的な目的のために、アンダースコアで始まる名前はreserved for the implementationであるため、先頭のアンダースコアなしで構造タグ名を再表示します。私は一緒に行くだろう:

typedef struct VisibleType VisibleType; 

ここで、タグとタイプ名は同じです。

1

構造体が隠されていると長所と短所があります。隠された構造体はコンストラクタなしでクライアントによって決して割り当てられません。隠された構造体はデストラクタを必要とし、クライアントはそれを呼び出すことを覚えておく必要があります。これは、要件に応じて利点または短所です。

#include <stdio.h> 
#include <stdlib.h> 

/*VIVIBLE.h*/ 
typedef struct 
{ 
    int number; 
}VISIBLE; 
void VISIBLE_INIT(VISIBLE * me, int num); 
void VISIBLE_PRINT(const VISIBLE * me); 

/*VIVIBLE.c*/ 
void VISIBLE_INIT(VISIBLE * me, int num) { if(me) me->number = num; } 
void VISIBLE_PRINT(const VISIBLE * me) { if(me) printf("%i\n", me->number); } 

/*SECRET.h*/ 
struct CLIENT; 
void CLIENT_CTOR(struct CLIENT ** me, int num); 
void CLIENT_DTOR(struct CLIENT ** me); 
void CLIENT_PRINT(const struct CLIENT * me); 

/*SECRET.c*/ 
typedef struct CLIENT 
{ 
    int number; 
}CLIENT; 
void CLIENT_CTOR(CLIENT ** me, int num) 
{ 
    if (me) 
    { 
     *me = (CLIENT*)malloc(sizeof(CLIENT)); 
     (*me)->number = num; 
    } 
} 
void CLIENT_DTOR(CLIENT ** me) 
{ 
    if (me && *me) free(*me); 
    *me = 0; 
} 
void CLIENT_PRINT(const CLIENT * me) { if(me) printf("%i\n", me->number); } 

/*main.c*/ 
void visible() 
{ 
    VISIBLE vis; // client can allocate memory 
    VISIBLE_INIT(&vis, 4); 
    VISIBLE_PRINT(&vis); 
    //if there is no need for a destructor the client does not need to call one 
} 

void hidden() 
{ 
    CLIENT * hidden; 
    CLIENT_CTOR(&hidden, 3); 
    CLIENT_PRINT(hidden); 
    CLIENT_DTOR(&hidden); //Client is never allowed to forget the destructor 
} 

int main() 
{ 
    visible(); 
    hidden(); 
} 
関連する問題