- ベストアンサー
オブジェクト指向コンパイラのインスタンスの構造について
インタプリタやコンパイラの中身について興味があり勉強しています。といってもまだ簡単な字句解析や構文解析のレベルです。 読んだ本にはオブジェクト指向言語については書かれていませんでした、そこで一つ疑問に思ったこと点について質問させてください。 簡単な言語の場合、使用する変数が宣言されると、その領域がスタックやヒープ空間に確保されるという風に理解しました。 一方オブジェクト指向言語にて、あるクラスのインスタンスを生成した場合を考えます。インスタンスには変数の他に関数やメソッドといった処理手続きが含まれていますよね。その手続きをコンパイルしたコードは何処に置かれているのでしょうか? 手続きのコードもヒープ空間に確保された各インスタンスの領域にコピー(?)されて実行されるのでしょうか。それとも処理手続きの実体は実行プログラムに含まれていて全インスタンスで共通で利用するようになっているのでしょうか。 初心者の素朴な疑問です、ご回答いただければ幸いです。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
ああ、嘘をついてしまいました。コンパイル時には、マングリングした上で、クラスの情報も何らかの形で残す必要がありますね。 動的なポリモーフィズムの実現のためには、コンパイル後にもクラスの関数情報を持った何らかの構造体が必須になります。 基本的には、子クラスは親クラスへのポインタを保持し、それを利用して親クラスの関数を参照するということになるでしょう。
その他の回答 (2)
- beefisdead
- ベストアンサー率63% (92/145)
オブジェクト指向であるのはソースコードまでで良いのです。あとはコンパイラの方で、それを矛盾無くフラットなコードに落とし込むことになります。 Javaには、thisというキーワードがあり、thisを使うとオブジェクト自身のメンバを呼び出すことができます。いっぽうでPythonでは、メンバ関数の最初の引数に自分自身を渡します。これは、Javaでは関数に暗黙的にオブジェクト自身を渡していたのが、Pythonにおいては明示的に渡している、と考えることができます。 C++では、関数の名前はコンパイル時に「マングリング」されます;すなわち、名前を変更されます。これは、C++の段階で持っていた名前空間をオブジェクトコードに落とし込んだときに矛盾無く持ち続けるためのものです。 最初の例では、メンバ関数が「オブジェクト自身を渡すだけのグローバルな関数」であっても実装が可能であるということを示しました。また二つ目の例では、名前空間のコントロールをコンパイル時に行うことが可能だと言うことを示したつもりです。 もちろん、より構造化された設計も考えられます。マングリングするよりも、クラスの情報を保持するところの先頭アドレスからのオフセットによって呼び出す関数をコントロールした方がエレガントであるように思います。コンパイラではポインタが一回多くなるため好まれないかも知れませんが、インタプリタだったらこっちの設計の方になるでしょう。 ですから、疑問に対する直接の解答としては「全インスタンスで共通に利用するように作る方が普通」ということになります。 もっとも、私はコンパイラに関しては専門家ではなく、大した知識はありません。間違い等あるかも知れません。
- liar_adan
- ベストアンサー率48% (730/1515)
実行プログラムのレベルでは、 C言語の関数のように、1つだけ含まれていて、 全インスタンスで共通で利用するというのが普通です。 実行時には、インスタンスの情報(ポインタ)を自動的に付加して、 呼び出すということになります。 全部のオブジェクト指向言語処理系でそうなっているかどうかは わかりませんが、C++やJavaなど一般的なものはそのはずです。 第一、インスタンス毎にコードをコピーしていたら、 メモリがもったいないです。
お礼
やはりメモリの利用効率を考えると共通利用するほうが合理的ですよね。もしかしてインスタンスの独立性(?)を高めるため(?)にコピーして持ったりするのかなと疑問に思い質問しました。 ご回答ありがとうございました。
お礼
詳しいご説明ありがとうございました。 今の私のレベルでは少々難しいご回答なのですが、時間をかけて理解していきたいと思います。