19

プログラミングの問題を提示されると、頭の中で自然にそれらを論理的なオブジェクトに分解し始めます。誰が何の責任を負い、誰が何を所有し、誰が何から派生するかなど。

私はCに苦労しています.手続き型言語で物事を行う方法がわかりません。

経験豊富な C プログラマーは、設計時に自分のプログラムについてどのように考えるべきかを説明してくれますか?

たとえば、独自の Semaphore クラスを書きたいとします。当然、自分のプログラムにも Queue データ構造が必要になります。これも自分で書きたいと思います。これを Java または C# で行う必要がある場合は、簡単な Queue クラスを作成し、Semaphore クラスでその新しいインスタンスを作成するだけで済みます。

しかし、C にはオブジェクトがありません。Queue データ構造のすべての動作をインライン化する必要がありますか?

誰かが私を「手に入れる」のを手伝ってくれますか?

関連cでアプリケーションの開発を計画および編成する最良の方法は何ですか

4

9 に答える 9

31

しかし、C にはオブジェクトがありません。Queue データ構造のすべての動作をインライン化する必要がありますか?

いいえ。

これを行う。

  1. OO 設計を快適に行えるように、クラスを定義してください。

  2. クラスの属性を C 言語の構造体として記述します。

  3. その構造体を、その構造体で動作するすべての関数とともにヘッダー ファイルに入れます。MyStruct * selfaがこれらすべての「メソッド関数」の最初の引数であることを確認してください。

  4. メソッド関数のすべての本体を含む C モジュールを作成します。

Cの貧乏人のOO。うまくいきます。必要なすべてのものを構造体に入れることについては、規律を守ってください-パブリックおよびプライベートインスタンス変数-すべて。

一般に、最初からプライベート変数を持つことは避けてください。OO コンパイラのすべての機能を利用できるわけではないため、「プライベート」や「保護」などの価値の低い機能を気にしないでください。

于 2009-03-23T18:57:49.873 に答える
17

構造体のメンバーのデータ非表示を実行するために不透明なポインターを使用するようにS.Lottの回答を修正します。

  1. 通常のオブジェクト指向デザインを使用して、クラスを定義します。
  2. クラスのメンバー変数は、C言語の構造体に入ります。
  3. ヘッダーファイルでは、オブジェクトのメンバー変数を公開したくありません(これらはオブジェクト指向言語では「プライベート」であるため)。代わりに、不透明なポインタを使用してください。
    typedef struct mystruct_s *mystruct_t; // first argument to all your methods
  4. 「公開」したいすべてのメソッドについて、それらのシグネチャを.hファイルに入れます。メソッド本体は.cファイルに入れる必要があり、「プライベート」メソッドは.cファイルでのみ定義し、静的に宣言して、それらのシンボルが他のファイルで定義されたシンボルと衝突しないようにする必要があります。

このメソッドを使用すると、アンダースコアなどの巧妙な命名規則は不要ですが、すべてのメンバー変数がプライベートになることを意味します。mystruct_push()関数はパブリックまたはプライベートにすることができますが、パブリック関数はグローバル名前空間の一部であるため、名前を、mystruct_pop()などの「パッケージ」名で修飾することをお勧めします。

また、発信者またはライブラリがとの呼び出しに責任があるかどうかを明確にする必要がmalloc()ありfree()ます。mystruct_t *create()ほとんどの場合、あなたはとvoid destroy(mystruct_t *target)メソッドを持っているでしょう。

于 2009-03-23T19:19:39.137 に答える
15

C でオブジェクト指向を考えることができます。

構造体と、その構造体のインスタンスへのポインターを最初のパラメーターとして受け取る一連の関数を作成するだけです。

ポリモーフィズムに関しては、構造体の最初のメンバーとして構造体のサイズを渡すことができるので、キャストする方法がわかります。

ANSI-C を使用したオブジェクト指向プログラミングの優れたPDF がここにあります。

于 2009-03-23T18:49:29.783 に答える
4

私は手続き型から OO の考え方に移行する時代のクマを持っていたので、あなたの痛みを感じます。

オブジェクトの作成方法を学ぶには、呼び出し元にどのように見えるかを考えるのが最善であることがわかりました。同じアプローチがあなたを助けるかもしれません。コンポーネントへの API がどのようになるかを検討してください。良い方法の 1 つは、既存の C API を調べることです (OO API の例として、標準の Java API を使用しました)。

次のようなキュー コンポーネントの使用に慣れています。

import some.package.Queue;

Queue q = new Queue(); 
q.add(item);

典型的な C API では、次のようなものが期待されます。

#include <queue.h> // provides queue, make_queue(), queue_add(), others

queue q = make_queue(); // queue is probably a struct, or a struct*
queue_add(q,item);

オブジェクトで考えていることに気付いたときはいつでも、同様の変換を行います。

関数へのポインターなどを使用して、C でオブジェクトのような構造を作成できますが、何千人もの C プログラマーがこれを使用せずに管理しています。

幸運を!

于 2009-03-23T20:10:34.207 に答える
2

LuaCapiをチェックしてください。Cインターフェースの設計に関しては、これが私の指針となっています。すべての関数は、Lua状態を先頭の引数として取り、これが「this」になります。継承は少しトリッキーですが、Chipmunkは、一般的な形状の構造体を取り、「klass」を介して実際に呼び出される関数の詳細を解明する関数を公開するのに非常に優れています。多くの場合、void *を利用して、OOでオーバーロードする方法で関数にさまざまなタイプ(構造体)を使用させることができます。時々少しハックを感じることがありますが、うまく機能します。

于 2009-03-23T19:51:46.593 に答える
1

もともと C++ は、C++ ソースから C コードを記述した単なるコンパイラでした。それらはその後、ネイティブ C コンパイラーによってコンパイルされ、リンクされました。

したがって、すべての OOP メソッドは C で使用できます。コンパイラは役に立たず、テンプレート、演算子のオーバーライド、データの隠蔽などのコンパイル時の機能をすべて提供するわけではありません。

  1. C++ の「構造体」は (おそらく今でも) すべてのメンバーが「パブリック」である「クラス」と同等でした。
  2. メンバー関数は、構造体の関数ポインターとして実装できます。これにより、カプセル化とポリモーフィズムを提供できます。 コンストラクターは、ファクトリを使用していない限り、グローバル スコープに存在します。 デストラクタはメンバー関数にすることができます。
  3. getColor()setColor( )などのアクセサー メンバー関数を使用すると、内部の違いを緩和し、データを隠蔽できます。本当に必要な場合は、マクロで非表示にするという Brian Bondy の提案を使用できます。
  4. 実際には、ハッシュ テーブル、動的配列、リンク リストなどの標準コンテナーを提供する FOSS ライブラリが多数あります。
于 2009-03-23T22:37:20.347 に答える
0

私は「Cで貧乏人のOO」を行うための提案を2番目にしています。また、PerlのOOがどのように機能するかを確認するために時間をかけることでメリットが得られると思います。基本的に、OOはPerlで、インタプリタにインスタンスを暗黙の最初のパラメータとしてすべてのメソッドに提供させることによって実現されます。コンパイラーは適切なカプセル化を強制しないため、Cでも同じことを明示的に行い、非常に優れたコード編成を使用する必要があります。

ちなみに、不透明なポインタを使用すると、構造体のメンバーを非公開にすることができます。GNUプログラミングの標準と推奨事項には、基本的にすべてをvoid *にキャストし、typedefを使用して、渡されるはずの特定のタイプの不透明なポインターに名前を付けるという手法が含まれていたことを思い出します。(つまり、各「クラス」)

于 2009-03-23T19:34:24.107 に答える
0

glib、cライブラリをoophttp://library.gnome.org/devel/glib/2.20/で使用し ます

于 2009-04-05T04:03:46.713 に答える