* オブジェクト指向 -(by [[K]], 2014.05.22) ** (0) -(ここに書いていることは2014年度内には実現しません!) -何年か先には、OSECPU-VMでもオブジェクト指向言語を作ることになると思います。もし僕が作ることになったら、C++言語を参考にすると思います。ここに書くのはそれらに関するアイデアのメモです。 ~ -僕としてはC++を作りたいのではなくて、C++よりもよい「なにか」を作りたいです。とはいえ、C++を否定しているわけではないので、C++をC++としてOSECPU-VM上で作ってくれる人がいたらそれは歓迎します。 ** (1) -C++でvirtualなメンバ関数を含むクラスを作ると、内部では見えないメンバ変数が一つ追加されて、virtualな関数へのポインタが並んだ配列を指し示すように初期化されます。 --例: class C { int a, b; virtual void setA(int _a) { a = _a; } virtual void setB(int _b) { b = _b; } }; sizeof (C) は { TypeInfo *info; int a, b; } から計算して12バイトになる。 TypeInfoにはsetAやsetBのポインタが格納されている。 この仕組みのおかげでこんなことができます。 class C を継承して class D を作り、setBだけオーバーロードした場合、そのTypeInfoは setBのポインタが新しい関数を指しているので、正しく子クラスの関数ポインタを得ることができ、 うまく呼び出せます。 -つまりC++でvirtualなメンバ関数を呼び出す場合は、オブジェクトからinfoの値を呼び出して、そしてその中からメンバ関数のポインタを取得して、それを呼び出すようなコードになっています。 -infoの構造(何番目の関数ポインタがsetBを指しているのか)などは、基本的に固定で、継承されるたびに新しいvirtual関数が付け足されていきます。 -このような仕組みになっているので、オブジェクトが一つでもあれば、そこからメンバ関数のポインタを取得することができます。 ~ -このinfoは「仮想関数テーブル」と呼ばれていて、vtableと表すのが一般的のようです。 --http://ja.wikipedia.org/wiki/%E4%BB%AE%E6%83%B3%E9%96%A2%E6%95%B0%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB ** (2) -C++の方式では、以下のような問題があります。 --あるクラスがあって、そのクラスにもsetAとsetBというメンバ関数があります(他の関数もある)。しかしこのクラスは上記の class C とは継承関係にはありません。この場合、このクラスに対して class C 向けに書かれた関数を利用することはできません。 --同じメンバ関数があれば、たとえ継承関係がなくても、同じように使えるべきだという考え方があって、それは「ダック・タイピング」と呼ばれていますが、僕はできるべきだと考えているのです。 ---http://ja.wikipedia.org/wiki/%E3%83%80%E3%83%83%E3%82%AF%E3%83%BB%E3%82%BF%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0 --これができる言語もあります。 --上記のWikipediaのページでは、C++でもテンプレートを使うことでこれを実現しています。しかしこれで生成されるコードは、各型ごとのtestが作られているだけなのです。それは僕がやりたいこととは違うのです。つまりC++のテンプレートによる解決は、ソースの行数は減らしたけれど、実際に生成されるコードの量は減っていないのです。 -僕の考える方式では、違った考え方をします。 -まず、関数のポインタをオブジェクトの中から取得することをやめます。それは呼び出し元からもらうのです。 C++方式: void func(C *c) { c->setA(13); } 提案手法: void func(C *c, Func *setA) { (*setA)(c, 13); } // イメージ. -提案手法を厳密に書くとややこしくなるので雑にしていますが、イメージは分かると思います。 -setAとsetBを使うのだとしたら、その両方のポインタを引数で渡してやればいいじゃないですか。それをオブジェクトから自動で求められるようにしようとしたから、C++はダック・タイピングができなくなってしまったのです。呼び出し元が関数のポインタを教えてあげる方法なら、必要なメンバ関数がそろっていれば、問題なく利用できます。 --もちろん毎回必要なメンバ関数を引数に列挙しなければいけなくなったら、それは大変です。でもそれは高級言語の方でカバーしてもらえばいいのです。 -この方式だと、setAとしてsetBをあえて使わせる、みたいなことも可能です。つまり対応する機能があれば、関数名が一致していなくてもいいのです。 -この方式だと、setAの代わりにsetBをあえて使わせる、みたいなことも可能です。つまり対応する機能があれば、関数名が一致していなくてもいいのです。 -このアイデアは、Cの<stdlib.h>のqsort()を思い出したときに思い付きました。・・・この仕様は良く考えられていて、十分に応用がきくと思います。 --たとえばソートはいろいろな順序でやりたいはずで、それは比較関数を変えるだけで制御できます。もしこれがcompareというメンバ関数をもつ、比較可能なクラスにのみで利用可能だとしたら、比較方法を1種類しか実装できないことになってしまいます。 * こめんと欄 #comment