C でオブジェクト指向のコードを書くにはどうすればいいでしょうか? [closed] 質問する

C でオブジェクト指向のコードを書くにはどうすればいいでしょうか? [closed] 質問する

C でオブジェクト指向コードを書く方法にはどのようなものがありますか? 特にポリモーフィズムに関して教えてください。


Stack Overflowの質問も参照してくださいCにおけるオブジェクト指向

ベストアンサー1

ポリモーフィズムについて話しているのであれば、はい、できます。私たちは C++ が登場する何年も前から、そのようなことをやっていました。

struct基本的に、データとそのデータに関連する関数を指す関数ポインターのリストの両方を保持するために を使用します。

したがって、通信クラスでは、オープン、読み取り、書き込み、クローズの呼び出しがあり、これらは、オブジェクトのデータとともに、構造体内の 4 つの関数ポインターとして維持されます。次のようになります。

typedef struct {
    int (*open)(void *self, char *fspec);
    int (*close)(void *self);
    int (*read)(void *self, void *buff, size_t max_sz, size_t *p_act_sz);
    int (*write)(void *self, void *buff, size_t max_sz, size_t *p_act_sz);
    // And data goes here.
} tCommClass;

tCommClass commRs232;
commRs232.open = &rs232Open;
: :
commRs232.write = &rs232Write;

tCommClass commTcp;
commTcp.open = &tcpOpen;
: :
commTcp.write = &tcpWrite;

もちろん、上記のコード セグメントは、実際には などの「コンストラクター」内にありますrs232Init()

そのクラスから「継承」する場合、ポインターを変更して独自の関数を指すようにします。これらの関数を呼び出すすべての人が関数ポインターを介して呼び出し、ポリモーフィズムを実現します。

int stat = (commTcp.open)(commTcp, "bigiron.box.com:5000");

手動 vtable のようなものです。

ポインタを NULL に設定することで仮想クラスを作成することもできますが、動作は C++ とは少し異なります (コンパイル時のエラーではなく、実行時にコア ダンプが生成されます)。

以下は、それを示すサンプル コードです。まず、最上位のクラス構造です。

#include <stdio.h>

// The top-level class.

typedef struct sCommClass {
    int (*open)(struct sCommClass *self, char *fspec);
} tCommClass;

次に、TCP サブクラスの関数を示します。

// Function for the TCP 'class'.

static int tcpOpen (tCommClass *tcp, char *fspec) {
    printf ("Opening TCP: %s\n", fspec);
    return 0;
}
static int tcpInit (tCommClass *tcp) {
    tcp->open = &tcpOpen;
    return 0;
}

HTTP の場合も同様です:

// Function for the HTTP 'class'.

static int httpOpen (tCommClass *http, char *fspec) {
    printf ("Opening HTTP: %s\n", fspec);
    return 0;
}
static int httpInit (tCommClass *http) {
    http->open = &httpOpen;
    return 0;
}

最後に、実際に動作するテスト プログラムを示します。

// Test program.

int main (void) {
    int status;
    tCommClass commTcp, commHttp;

    // Same 'base' class but initialised to different sub-classes.

    tcpInit (&commTcp);
    httpInit (&commHttp);

    // Called in exactly the same manner.

    status = (commTcp.open)(&commTcp, "bigiron.box.com:5000");
    status = (commHttp.open)(&commHttp, "http://www.microsoft.com");

    return 0;
}

出力は次のようになります:

Opening TCP: bigiron.box.com:5000
Opening HTTP: http://www.microsoft.com

サブクラスに応じて異なる関数が呼び出されていることがわかります。

おすすめ記事