C言語の構造体のprivateメンバ

2008年5月18日は°で掲示されるC / C + +

今週、ここでは、職場でのプログラミングパラダイムが独立した完全に言語何かである、つまり、あなたがでプログラミングをしているため、選択されていないことを複数の証拠を持っていたC + +でコンパイルg + +のコードは、オブジェクト指向になることので、少し、あなたのコードは、ANSI Cの場合は、プログラムを構造化する必要がありますかは、オブジェクト指向プログラミングから失格となります。

私は、ANSI Cの右、オブジェクト指向を読んでいる?

yesとno!

継承、ポリモーフィズム、オーバーロードのようなものはC言語で作る/エミュレートするために複雑であるが、オブジェクト指向と同じように行儀のスタイルを使用してプログラムすることができます。 libdfbは、それがオブジェクトとほぼ同じように振る舞うの要素を破壊する操作を、ユーザーが作成するように、C言語で書かれてが、"オブジェクト指向"される。

ここでは仕事で、我々がでGUIに接続するC言語でのシステムのハードウェアアブストラクションを持っているC + +。 最下位層は、また、オブジェクト指向をシミュレートし、これらのテクニックで(と非常によく書かれ、道で言う)Cで書かれています。 このような技法は、本Cのそれらの脚注のいずれかを身に着けていることによって私の注意を呼ばれる

それが再び他の単位でexternとして宣言されない限り、Cコードをコンパイルするとき、各シンボルは、それが宣言されたコンパイル単位内でのみ表示されます。 したがって、外の世界へにアクセス不可となり、そのコンパイル単位内で特定の記号を"隠す"ことができる。 我々は、このパッケージを使用している。

コンパイル単位は、前処理および単コンパイルされたオブジェクトコードを生成した後、ファイルのセットです。 基本的に(ただし、正確に)、我々は、ソースコードの各コンパイルユニットの実装ファイル(*. C、*. cppに。等)のために取ることができます。 上で詳細コンパイルの手順CとC + +で検出することができるブログCaloni

この情報を使用して、我々は、その内部のメンバーがされているANSI C言語で構造体を作成できる"プライベートを。" 魔法は、コンパイル単位内のトラップ状態の定義にあり、これらのメンバーのアクセスメソッドを作成します。 このため我々は、私たちはCの要素の宣言と定義の違いを示す脚注を使用します。

宣言または声明:コンパイラは、その意味についてはあまり言わずに識別子を提示する、すなわち、識別子のXXXが存在することをコンパイラに通知しますが、少しはそれが何を表しているのかについては知られている。
例:

  a ; にextern int型 ;
 void ) ; ボイド何とか(ボイド);
 構造体 st_data; 

定義と実装は:識別子は、そのような他のもののうち、どのくらいのメモリをそれに割り当てられていると私たちはそれを見つけることができるメモリのアドレスする必要があるとして、与えられていることをコンパイラーに指示します。
例:

  int型 ;
 void ) { /* Do anything. ボイド何とか(ボイド){/ *何もしないでください。  * /}
 /* Some members. st_data 構造体 {/ *メンバーを追加する。  * /} 

我々は何もあなたがその型の変数を必要とするどのくらいのスペースについて知られていないため、コンパイラはそれらのためにメモリを割り当てることができない定義せずに、構造や種類について話すときに。 一方、時々、主張することなく、リンカがそのシンボルが存在するのかを知ることができません。

我々は、ヘッダーの構造体を宣言するときに、通常我々はまた、そこに彼らのメンバーを設定して、我々のソースにヘッダを追加するすべてのこの時間は、我々はこの構造体の定義として、ソース文、両方が公共estuturaのメンバーを作っているコンパイル単位に含まれているこのコンパイル単位に。 これは、私たちは直接メンバにアクセスすることができます。

我々は構造を表す定義のみシンボルの別々のステートメントは、そのメンバーではない可能ですが、場合。 このように、メンバへのアクセスを指示しようとすると、コンパイルエラーが生成されます。 興味深い副作用は、コンパイラが構造体のサイズについて何も知らないとして、すべてのポインタが同じサイズを持っていると、コンパイラはシンボルの名前だけを必要とするため、あなたが直接型構造、それに対する唯一のポインタ、の変数を定義できないことです作成するポインタの型。

我々は、このようなヘッダをmytype.h:

 #ifndef命令は#MY_TYPE_H MY_TYPE_H /を 定義 *のtypedefは単に単語の構造体を繰り返し続けるものではない。  _mytype * / / * _MYTYPE構造体* / typedefは構造体 _MYTYPE:* / / *ステートメントが唯一の通路です。 

実装mytype.c:

  #"mytype.h"を含める

 FOPEN
 #含める
 #<string.h>に含める

 /* Aqui fica a definição da estrtura. _MYTYPE 構造体は {/ *ここでestrturaの定義です。  * /
     /* Somente depois disso é que o com- */ int型データ/ *のみその後、with - *系/
     21 ] ; /* pilador vai saber como alocá-la. int型テキスト[21] / * piladorは、これを確保する方法を知っているだろう。  * /
 /* Tente um sizeof(my_type) no main. ;} / *メインにはsizeof(my_typeを)みてください。  * /

 my_type ** my_ptr ) { /* some code... create_my_type ボイド (** my_type my_ptr){/ *いくつかのコード...  * /}
 my_type ** my_ptr ) { /* some code... destroy_my_type ボイド (** my_type my_ptr){/ *いくつかのコード...  * /}
 my_type * my_ptr , int d ) { /* some code... set_data ボイド (* my_type my_ptr、INT D){/ *いくつかのコード...  * /}
 my_type * my_ptr ) { /* some code... int型 get_data(my_type my_ptr *){/ *いくつかのコード...  * /}
 my_type * my_ptr , const char * text ) { /* some code... ボイド関数set_text(my_type my_ptr *、const char *を テキスト ){/ *いくつかのコード...  * /}
 get_text ( my_type * my_ptr ) { /* some code... GET_TEXT はchar *(* my_type my_ptr){/ *いくつかのコード...  * /} 

完全なソースコードの例を見つけることができるここに

あなたが直接そのような変数を作成することはできないので、我々は"ビルダー"と"デストラクタ"を定義する必要があります。

メンバーへのダイレクトアクセスの試みは、コンパイルエラーを生成:

  private-struct-members$ gcc -o teste mytype.h mytype.c main.cユーザ@ホスト:〜/民間の構造体のメンバーは$ gccの- Oテストのmain.c mytype.h mytype.c
のmain.c:"main"関数で:
main.c:22:エラー:不完全なへの間接参照ポインタ
 private-struct-members$ユーザ@ホスト:〜/民間の構造体のメンバーは$ 

従って、少しの工夫で、両方の言語パラダイムの概念を、それは本当に興味深いコードを実装することは可能です。 この愚かな例では、エミュレーションのパッケージを強制的に有用性またはCで、しかし、状況がC + +、または複雑さが重大なレベルに到達する傾向がある、これらのテクニックは許可されていないシステムでは、コンストラクタ/デストラクタの使用をクリアしないことがあります大きな価値のショー。 私たちのケースでは、このテクニックは特に構造体のメンバへの直接アクセスに、彼の試みは、文脈上不適切であることを発見した、プロジェクト全体を、出席しなかった経験豊富なプログラマーを許可。 それがなければ、バグカブールのロジックは、ソフトウェアは、おそらく顧客の顔で爆発すること、実行時にのみ現れます。

便利なリンク(またはしない...):
http://www.directfb.org
http://www.caloni.com.br
http://www.numaboa.com.br/informatica/c/
Linuxカーネル開発の本

コメント

  • ディオゴV. Kersting

    どこでソースコードをダウンロードできますか?
    http://blabos.org/blog/wp-content/uploads/2008/02/stopwatch.zip

  • うっかり漏らす

    おやすみなさい

    ご清聴ありがとうございました。

    私は、ブログサーバを変えてきたといくつかのリンク切れを終わった。 私はこれを修正します。

    抱擁

  • うっかり漏らす

    約束どおり、彼はそこにあります

    抱擁

  • うっかり漏らす

    私はここに、意味する:

    http://src.blabos.org/blog/posts/17/stopwatch.zip

  • ロドリゴマルティンス(魔女)

    それは何か新しいハァッAHHuahuAHUahuAを投稿してみましょう

  • うっかり漏らす

    魔女はい、あなたは正しい、しかし骨大丈夫です...

    幸い、私はオーブンで何かを持っている :)

    抱擁

  • Carcara

    また、それらが静的宣言の外部での関数のコンパイルユニットを非表示にすることができます - これはまた、グローバル変数の場合はtrueです。 したがって、外付けドライブは、存在を知らないでしょうし、静的な関数は、それが別のファイルでexternとして宣言されて防ぐことができます。

Disqusを搭載ブログのコメント