3

私は、すべて Web ベース (PHP、javascript、一部の python) の高水準言語をいくつか知っています。私は最終的に下位レベルの言語を学ぶことに決め、C を使用することにしました。問題は、私が使用するすべての言語が OOP に大きく基づいていることです。(私が行った調査に基づいて)Cにはクラスや継承がありません。その結果、私はあなたにこう尋ねます: 言語を切り替えたり、無数の関数を含むファイルを持ったりすることなく、OOP のように組織化された方法で C でコードを整理するにはどうすればよいですか?

未来から編集:この質問は、振り返ってみるとかなりばかげています。私は 15 歳で、学校には CS がありませんでした...

4

5 に答える 5

18

C は、コード編成の点で多くを提供しません。関数とファイルがあります。

非表示の実装またはプライベート関数を使用してインターフェイスを実装する場合は、"foo.h" と "foo.c" などの 2 つのファイルを作成します。

インターフェイスおよび/またはパブリック関数は「foo.h」の関数プロトタイプであり、関数は「foo.c」に記述されています。さらに、非表示の実装またはその他のプライベート関数は「foo.c」にありますがstatic、 などのようにマークされていstatic int foo_internal_function(int i);ます。マークされた関数はstatic、それらが存在するファイル内でのみ参照でき、他のファイルでは参照できません。

正式な名前空間はありませんが、関数名の前にFoo_discombobulate_developers(). クラスはありませんが、少なくともファイルでカプセル化効果を得ることができます。拡張可能な階層はなく、ファイルと関数だけです。

C は後の言語の組織に近いところはありませんが、多くの非常に優れたプログラムが C で作成されています。注意して、紛らわしいものにはコメントを付けて (C では紛らわしいものがある可能性があります)、適切なメモをとってください。

于 2009-09-25T21:19:36.260 に答える
9

「機能が無限にあるファイル」

本当に必要なのは、明確に定義され、制限された関数のセットを備えたファイルです。これはモジュラープログラミングと呼ばれます。アイデアは、機能に基づいて関数を単一のコンパイルユニットにグループ化し、ヘッダーで関数プロトタイプを定義することです。

Foo.h:

int GetFoo();

Foo.c:

int GetFoo()
{
   ...
}

これは、一連のメソッドを1つのクラスにグループ化する方法にいくぶん似ています。主な違いは、いつでも作業している「これ」が存在する場合と存在しない場合があることです。つまり、Cで本質的に「オブジェクト指向」プログラミングを行うことができます。ただし、オブジェクトはモジュールのパラメータになります。これが1つのアプローチです:

Bar.h:

typedef int BAR_OBJ

BAR_OBJ MakeBar();

int GetBarSize(BAR_OBJ);

void DoFooToBar(BAR_OBJ, ...)

Bar.c

   struct BarDetails
   {
      int isFree;
      int size;
      ...
      // other info about bar
   };

   static BarDetails arrayOfBars[...]; // 

   BAR_OBJ MakeBar()
   {
       // search BarDetails array, find free Bar    
   }

   int GetBarSize(BAR_OBJ obj)
   {
       return arrayOfBars[obj];
   }

   void DoFooToBar(BAR_OBJ, ...)
   {
      // lookup bar obj and do something
   }
于 2009-09-25T21:08:43.977 に答える
4

それでもOOを実行したい場合は、C++を使用してください。

OOなしで本当にCのみを使用したい場合は、ロジックを複数のファイルに分割し、すべてのソースファイルを単一のオブジェクトと見なします。したがって、すべてのファイルは、その単一の構造に密接に関連する構造と機能のみを保持します。

于 2009-09-25T21:08:35.677 に答える
4

OOP をエミュレートする C で頻繁に現れるパターンを次に示します。

MyClass という名前のクラスを考えてみましょう。

/* MyClass.h or myclass.h */

#ifndef MYCLASS_H
#define MYCLASS_H

struct myclass_s;
typedef struct myclass_s myclass_t;

myclass_t * myclass_new();
void delete_myclass(myclass_t *);

    // Method int doMyStuff(int arg1,int arg2)
int myclass_doMyStuff(myclass_t *, int arg1, int arg2);

#endif //MYCLASS_H

ヘッダー ファイルはタイプ myclass_t を定義しますが、実際の実装 myclass_s を隠します。この 2 つの名前を持つというやや厄介な要件は、C では構造体が別の名前空間にあるのに対し、C++ では構造体は他のすべての型と同じ名前空間にあります。このコードは、C と C++ の両方で動作するように意図されています。対応する .c ファイルは次のとおりです。

/* MyClass.c or myclass.c */

#include "myclass.h" // Or MyClass.h

struct myclass_s {
   int exampleField;
};

myclass_t * myclass_new()
{
   myclass_t * o=(myclass_t*)malloc(sizeof(myclass_t));
   // Initialize o here.
   return o;
}

void myclass_delete(myclass_t * o)
{
   // Do any cleanup needed on o here.
   free(o);
}

int myclass_doMyStuff(myclass_t * o,int arg1,int arg2)
{
   // ...
}

継承と動的バインディングも C で行うことができますが、多少複雑になります。上記のパターン、または OOP をモデル化するパターンは、C で物事を行うための最良の方法であるとは限らないため、クラス中心の考え方にとらわれないようにしてください。それでも、このパターンが役立つ場合があります。たとえば、libpng はこれに近いものを使用します (彼らは setjmp/longjmp を使用して「例外」も行いますが、これは私が推奨するものではありません)。

于 2009-09-25T22:36:04.500 に答える
1

OOP っぽい C 用のGObjectがありますが、適切に設計された構造化プログラムは、同等の OOP のものよりも読み取り/保守が難しくないはずです。

于 2009-09-25T21:17:16.827 に答える