• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:継承したクラスを、継承元のクラス型の引数に渡すとどうなるのでしょうか?)

継承したクラスを継承元のクラス型の引数に渡すとどうなるのでしょうか?

このQ&Aのポイント
  • 継承したクラスを継承元のクラス型の引数に渡すと、コンパイルは通り実行結果も期待通りになりますか?
  • 継承先のクラスが独自のメンバを持っている場合はどうなるのでしょうか?
  • コードの実行結果が期待通りになるかどうか、継承元と継承先の関係に注意が必要です。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

言語仕様通りで問題ありません。 実行時の挙動の話をすると、 1.プログラムは関数と変数に分けられてメモリ上に配置される プログラムがメモリにロードされて命令が実行される段階では、プログラムはテキスト領域、静的領域、ヒープ領域、スタック領域に分けられて実行されます。 テキスト領域には、関数が機械語に翻訳された内容が格納されますので、このことからメンバ関数を増やしても問題になりません。 2.メンバ変数は基底(継承元)クラスのメンバの後に継承クラスのメンバが継ぎ足しされる。 hoge のインスタンス(obj)のメモリ上の配置 1000から1019のアドレスにobjは格納される。 1000から1011のアドレスにobjのbaseクラスのメンバが格納される。 1012から1019のアドレスにobjのhogeクラスのメンバが格納される。 1000: base.m_nII; // base クラスのメンバ変数(obj) 1004: base.m_nJJ; // 〃 1008: base.m_nKK; // 〃 1012: hoge.m_anpan; // hoge クラスで追加したメンバ変数 1016: hoge.m_pizza; // 〃 3.メンバ関数は、構造体へのポインタを受け取る関数 「func」関数の引数で「base *obj」を指定し「obj->GetSum()」と呼び出すことは 「static int base::GetSum(base *obj)」の呼び出しと同じである。 つまり、構造体へのポインタを引数とする関数に等しい。 // 以上のことをC言語に直すとこんな風になります。 struct base { int m_nII, m_nJJ, m_nKK; }; struct hoge { struct base base; int m_anpan, m_pizza; }; void base_init(struct base *obj, int i, int j int k) { obj->m_nII = i; obj->m_nJJ = j; obj->m_nKK = k; } int base_GetSum(struct base *obj) { return obj->m_nII + obj->m_nJJ + obj->m_nKK; } void hoge_init(struct hoge *obj) { base_init((struct base *)obj, 1, 2, 3); obj->m_anpan = 120; obj->m_pizza = 3000; } int hoge_GetPizza(struct hoge *obj) { return obj->m_pizza; } int main() { struct hoge obj; hoge_init(&obj); printf("sum is %d\n", base_GetSum((struct base *)&obj)); obj.m_anpan = 1200; printf("Anapn is \\%d\n", obj.m_anpan); printf("Pizza is \\%d\n", hoge_GetPizza(&obj)); // アドレス表示 printf("obj.base.m_II : %x\n" &obj.base.m_II); printf("obj.base.m_JJ : %x\n" &obj.base.m_JJ); printf("obj.base.m_KK : %x\n" &obj.base.m_KK); printf("obj.m_anpan : %x\n" &obj.m_anpan); printf("obj.m_pizza : %x\n" &obj.m_pizza); return 0; } ポイントは、クラスという概念は関数と構造体を一体的に扱う仕組みであり言語仕様上にのみ存在し、実行時にメンバ関数は単純な引数渡しと関数呼び出しになるということです。 関連として、関数のオーバーライド、ポリモルフィズムなどがありますが、それの実体は構造体のレコードに関数ポインタ配列へのポインタを持たせているだけです。 つまり理解するには、C言語の関数ポインタ、関数ポインタの配列について理解することが、遠回りですが近道になります。 # 理解しなくても使うことはできますが(ーー;) あと、コードっぽいのは適当に書いただけなので間違いがあると思います。

参考URL:
http://brain.cc.kogakuin.ac.jp/~kanamaru/lecture/MP/final/part06/node8.html
pokapoka1980
質問者

お礼

内部的なことまで理解でき、大変感謝です。 ありがとうございました。

その他の回答 (1)

  • anmochi
  • ベストアンサー率65% (1332/2045)
回答No.1

 全く問題ないですよ。よく使われる手法です。C++には欠かせないテクニックで、ポリモーフィズムを実現する方法の一つですね。  継承先のクラスが同名の独自のメンバを持っている(今回はhogeクラスがint GetSum()を持っていた)場合に、どっちが呼ばれるかは、このソースではbaseの方になります。これを、hogeの方を呼ばせたければbaseのint GetSum()にvirtualというキーワードをつけます。  この辺の詳しいお話は「オーバーライド」や「仮想関数(virtual)」などをキーワードに検索してみてください。