トーク:C言語/構造体・共用体

出典: フリー教科書『ウィキブックス(Wikibooks)』
ナビゲーションに移動 検索に移動

「構造体に関数を含むことはできない」は誤り[編集]

C++言語では構造体などのメンバに関数を含むこともでき「メンバ関数」などと呼ぶ。しかし、無印のC言語には、構造体に関数を含むことはできない(つまり、無印Cに「メンバ関数」の機能は無い)。

C言語にメンバ関数がないことは事実です。しかし構造体に関数を含めないからではありません。C言語には関数ポインタがあり、構造体に関数ポインタを含むことができます。マクロを併用することでオブジェクト指向プログラミングもできます。
「C言語では複雑なトリックや黒魔術が必要になる」は「C言語は〜ができない」とは異なります。C言語は不便かもしれません。しかし「不便」を「できない」に言い換えると嘘を教えることになってしまいます。 --Siglite3 (トーク) 2018年7月2日 (月) 21:11 (UTC)

構造体と関数ポインタの例を書いてみました。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAME_MAX 100

/* 商品を扱う構造体 Item_t */
typedef struct item {
    char name[NAME_MAX];                /* 商品名 */
    int  price;                         /* 価格 */
    void (*add_tax)(struct item*, int); /* 関数ポインタ */
} Item_t;

/* Item_t.price に消費税 (sales tax) を掛ける関数 */
static void add_seles_tax(Item_t* self, int seles_tax) {
    self->price += self->price * (seles_tax / 100.0);
}

/* Item_t を初期化して返す関数 */
Item_t* new_item(const char* product_name, const int before_tax_price) {
    Item_t *item = calloc(1, sizeof(Item_t));
    
    strncpy(item->name, product_name, NAME_MAX);
    item->name[NAME_MAX-1] = '\0';      /* バッファオーバーランを防止 */
    item->price   = before_tax_price;   /* before_tax_price は税抜価格 */
    item->add_tax = add_seles_tax;      /* 関数ポインタに add_sales_tax() をセット */
    
    return item;
}

int main(void)
{
    Item_t *coffee = new_item("コーヒー", 300);
    printf("%s: 税抜き %d 円\n", coffee->name, coffee->price);
    //=> "コーヒー: 税抜き 300 円"
    
    /* 構造体に関数ポインタを入れると C++ のメンバ関数みたいに使える */
    coffee->add_tax(coffee, 8);
    
    printf("%s: 税込み %d 円\n", coffee->name, coffee->price);
    //=> "コーヒー: 税込み 324 円"

    return 0;
}

このように構造体に関数(厳密に言えば関数ポインタ)を含むことができますし、メンバ関数はありませんがメンバ関数のように使えます。--Siglite3 (トーク) 2018年7月5日 (木) 13:24 (UTC)