Navigation Log - なびろぐ -
1999/06/25

...X680x0 spirit inside...

この日記はGNSで生成しています。
この日記の画像はOPTPiX webDesigner Ver.4で生成しています。

hauN
Go amazon.co.jp

■ご注文リストから■ [一覧]
■Amazonギフト券■ [購入]
ゆゆ式 7巻 []
ゆゆ式 7巻
Amazonほしい物リスト


1999/06/25 (金)

クラスの正体

_ こういった疑問って、コンパイラが吐くソースの身になるとすぐ解消できたりする。きっと、こういうコンパイル結果を吐いているはず・・・Cで書いてみる。


void AA_hello_void(void)
{
  /* "I am AA"を表示 */
}

void AA_hello_int(int i)
{
  /* "I am AA"+iを表示 */
}

typedef char *string;
void CC_hello_string(string p)
{
  /* "I am AA"+pを表示 */
}

typedef struct {
  void (*AA_hello_void)(void);
  void (*AA_hello_int)(int);
} T_AA;
T_AA AA = { AA_hello_void, AA_hello_int };

typedef struct {
  void (*AA_hello_void)(void);
  void (*AA_hello_int)(int);
  void (*CC_hello_string)(string);
} T_CC;
T_CC CC = { AA_hello_void, AA_hello_int, CC_hello_string };

main()
{
  T_AA *obj;
  obj = malloc( sizeof(T_AA) );
  memcpy( obj, CC, sizeof(T_AA) ); 
  /* ここまでが「AA obj=new CC();」に相当 */

  obj->AA_hello_int(256);
  obj->AA_hello_void();
  obj->CC_hello_string();  /* ←ここでエラーになるはず */
}

_ クラスのメソッドの羅列のコンパイル結果ってのは、ただの「ジャンプテーブル」でしかない。継承はぶっちゃけた話「元からあるテーブルに追加して新しいテーブルにする行為」でしかない。objが型AAで定義したにもかかわらず型CCを代入できるのは「CCはAAに追加したものであるから、つまりAAでもある」からで、CCで追加した分は代入されない。と考えれば、CCで追加したメソッドをAAの型のままで呼べるはずがないことは、明らか。

_ 仮想関数ってのは、


T_AA AA = { AA_hello_void, AA_hello_int };

の「AA_hello_?」の部分にNULLをとりあえず入れておく行為だと思えば、なぜコンパイルが通るようになったかもわかるはず。

_ 補足。ここではわかりやすくするために「ジャンプテーブルは中身をコピーする」ような記述にしたけど、実際はどっかに中身があって、「中身へのポインタ」しかコピーしない・・・でないと実行効率が悪すぎるはず。この場合、「CCで追加した分は代入されない」ということが嘘になってしまうが、「T_CCへのポインタをT_AAへのポインタにキャストした時点で、追加分が見えなくなる」ことで事実上同じ結果になっている・・・はず。


[URL] [View Log()] [Trackback]
Name: Comment:



メールはこちらへ...[後藤浩昭 / Hiroaki GOTO / GORRY / gorry@hauN.org]

「表紙へ戻る」
「会議室」 「最新版」 「なびろぐindex」 「GNSソースを読む」