「C言語/中級者向けの話題」の版間の差分

削除された内容 追加された内容
Ef3 (トーク | 投稿記録)
マークアップ修正
タグ: 2017年版ソースエディター
Ef3 (トーク | 投稿記録)
→‎オブジェクト指向プログラミング: C言語は一般にオブジェクト指向プログラミング言語だとは考えられていませんが、従前の構造体やマクロを使うことでクラスの継承に類似した実装を行うことができます。
タグ: 2017年版ソースエディター
401 行
上の例では、0か1かの値を持つ1ビットの8つのビットフィールドをもつbits構造体を宣言し各ビットフィールドに値を代入しその値を表示している。
なお、unsigned char型をビットフィールドに使えるかはコンパイラによる。
 
== オブジェクト指向プログラミング ==
C言語は一般にオブジェクト指向プログラミング言語だとは考えられていませんが、従前の構造体やマクロを使うことでクラスの継承に類似した実装を行うことができます。
 
;構造体やマクロを使った継承の例:<syntaxhighlight lang="C">
#include <stdio.h>
 
struct Shape {
double x, y;
void (* print)(struct Shape *);
double (* area)(struct Shape *);
};
 
struct Square {
struct Shape shape;
double wh;
};
static void printSquare(struct Shape* sp) {
struct Square *p = (struct Square *)sp;
printf("Square(x:%f, y:%f, wh:%f)", sp->x, sp->y, p->wh);
}
static double areaSquare(struct Shape* sp) {
struct Square *p = (struct Square *)sp;
return p->wh * p->wh;
}
#define Square(x, y, wh) (struct Shape*)&((struct Square){ {x, y, printSquare, areaSquare }, wh })
 
struct Rectangle {
struct Shape shape;
double w, h;
};
static void printRectangle(struct Shape* sp) {
struct Rectangle *p = (struct Rectangle *)sp;
printf("Rectangle(x:%f, y:%f, w:%f, h:%f)", sp->x, sp->y, p->w, p->h);
}
static double areaRectangle(struct Shape* sp) {
struct Rectangle *p = (struct Rectangle *)sp;
return p->w * p->h;
}
#define Rectangle(x, y, w, h) (struct Shape*)&((struct Rectangle){ {x, y, printRectangle, areaRectangle }, w, h })
 
struct Circle {
struct Shape shape;
double r;
};
static void printCircle(struct Shape* sp) {
struct Circle *p = (struct Circle *)sp;
printf("Circle(x:%f, y:%f, r:%f)", sp->x, sp->y, p->r);
}
static double areaCircle(struct Shape* sp) {
struct Circle *p = (struct Circle *)sp;
return 3.1415926536 * p->r * p->r;
}
#define Circle(x, y, r) (struct Shape*)&((struct Circle){ {x, y, printCircle, areaCircle }, r })
 
void print(struct Shape *p ) {
p->print(p);
}
double area(struct Shape *p ) {
return p->area(p);
}
int main(void){
struct Shape* shapes[] = {
Square(10.0, 20.0, 15.0),
Rectangle(20.0, 10.0, 12.0, 11.0),
Circle(15.0, 10.0, 10.0),
};
for (int i = 0; i < sizeof shapes / sizeof *shapes; i++) {
print(shapes[i]);
printf(", area = %f\n", area(shapes[i]));
}
}
</syntaxhighlight>
;実行結果:<syntaxhighlight lang="text">
Square(x:10.000000, y:20.000000, wh:15.000000), area = 225.000000
Rectangle(x:20.000000, y:10.000000, w:12.000000, h:11.000000), area = 132.000000
Circle(x:15.000000, y:10.000000, r:10.000000), area = 314.159265
</syntaxhighlight>
この例は、継承というより合成の例になっているという批判はありえます。
 
== 脚註 ==