忍者ブログ
趣味+メモ用のブログです。 GNU/Linux関連、OSS関連情報、調査事項になるでしょうが、何を書くか分かりません。
[79] [78] [77] [76] [75] [74] [73] [72] [71] [70] [69]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

C++の継承で実験


結果からいうと、
・ベースクラスのポインタで読んだメソッドは、
 ベースクラスのメソッドが呼ばれる。
 →型依存の呼び出し
・間接呼び出しをした場合、private/protectedに関係なく
 virtualをつけたメソッドは、オブジェクト実態が呼び出される
 →オブジェクト依存の呼び出し
・継承時の、virtualは効果がない
・virtualをつけたメソッドは、オブジェクト依存の呼び出し
・virtualをつけなかったメソッドは、クラス依存の呼び出し
となる。
 ■検証用コード(test.cpp)
 1 #include <stdio.h>
 2 
 3 // ベースクラス
 4 class Base{
 5 public:
 6 void direct(){ // 直接呼び出し用 
 7   printf( "Base::direct() \n" );
 8 }
 9 virtual void directVirtual(){
10   printf( "Base::directVirtual() \n" );
11 }
12 void indirect(){ // 間接呼び出し用
13   this->doPrivate();
14   this->doPrivateVirtual();
15   this->doProtected();
16   this->doProtectedVirtual();
17 }
18 private:
19         void doPrivate()       { printf( "Base::doPrivate() \n" ); }
20 virtual void doPrivateVirtual(){ printf( "Base::doPrivateVirtual() \n" ); }
21 protected:
22         void doProtected()       { printf( "Base::doProtected() \n" ); }
23 virtual void doProtectedVirtual(){ printf( "Base::doProtectedVirtual() \n" ); }
24 };
25 
26 // サブクラス1(普通に継承)
27 class Sub1: public Base{
28 public:
29 void         direct()       { printf( "Sub1::direct \n" ); }
30 virtual void directVirtual(){ printf( "Sub1::directVirtual() \n" ); }
31 private:
32         void doPrivate()       { printf( "Sub1::doPrivate() \n" ); }
33 virtual void doPrivateVirtual(){ printf( "Sub1::doPrivateVirtual() \n" ); }
34 protected:
35         void doProtected()       { printf( "Sub1::doProtected() \n" ); }
36 virtual void doProtectedVirtual(){ printf( "Sub1::doProtectedVirtual() \n" ); }
37 };
38 
39 // サブクラス2(virtualで継承)
40 class Sub2: public virtual Base{
41 public:
42 void         direct()       { printf( "Sub2::direct \n" ); }
43 virtual void directVirtual(){ printf( "Sub2::directVirtual() \n" ); }
44 private:
45         void doPrivate()       { printf( "Sub2::doPrivate() \n" ); }
46 virtual void doPrivateVirtual(){ printf( "Sub2::doPrivateVirtual() \n" ); }
47 protected:
48         void doProtected()       { printf( "Sub2::doProtected() \n" ); }
49 virtual void doProtectedVirtual(){ printf( "Sub2::doProtectedVirtual() \n" ); }
50 };
51 
52 
53 int main()
54 {
55     Base* ptr = NULL;
56     Base base;
57     Sub1 sub1;
58     Sub2 sub2;
59 
60     printf( "== Base ==\n" );
61     ptr = &base;
62     ptr->direct();
63     ptr->directVirtual();
64     ptr->indirect();
65 
66     printf( "== Sub1 ==\n" );
67     ptr = &sub1;
68     ptr->direct();
69     ptr->directVirtual();
70     ptr->indirect();
71 
72     printf( "== Sub2 ==\n" );
73     ptr = &sub2;
74     ptr->direct();
75     ptr->directVirtual();
76     ptr->indirect();
77 
78     return 0;
79 }

 ■結果
$ g++ --version
g++ (Debian 4.7.2-5) 4.7.2
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ g++ test.cpp
$ ./a.out
== Base ==
Base::direct()
Base::directVirtual()
Base::doPrivate()
Base::doPrivateVirtual()
Base::doProtected()
Base::doProtectedVirtual()
== Sub1 ==
Base::direct()
Sub1::directVirtual()
Base::doPrivate()
Sub1::doPrivateVirtual()
Base::doProtected()
Sub1::doProtectedVirtual()
== Sub2 ==
Base::direct()
Sub2::directVirtual()
Base::doPrivate()
Sub2::doPrivateVirtual()
Base::doProtected()
Sub2::doProtectedVirtual()

Javaだと、Sub1 / Sub2はすべて子クラス側の メソッドが呼び出されるため、注意が必要!!
ちなみに、独習C++での結果とはちがっている。
(すみません。あっています)
Javaと同様の動きにするには、メソッドにvirtualをつける必要がある。
ただし、virtualをつけることにより、命令数は増え、負荷は高くなる。
 ■ virtual有無によるアセンブルの確認
$ g++ -g test.cpp
$ objdump -C -S -l ./a.out
・・・
/home/sakaihdt/test/c++/subclass/test.cpp:62
    ptr->direct();
 80486c5:       8b 44 24 1c             mov    0x1c(%esp),%eax
 80486c9:       89 04 24                mov    %eax,(%esp)
 80486cc:       e8 a9 00 00 00          call   804877a <_ZN4Base6directEv>
/home/sakaihdt/test/c++/subclass/test.cpp:63
    ptr->directVirtual();
 80486d1:       8b 44 24 1c             mov    0x1c(%esp),%eax
 80486d5:       8b 00                   mov    (%eax),%eax
 80486d7:       8b 00                   mov    (%eax),%eax
 80486d9:       8b 54 24 1c             mov    0x1c(%esp),%edx
 80486dd:       89 14 24                mov    %edx,(%esp)
 80486e0:       ff d0                   call   *%eax
・・・
PR


忍者ブログ [PR]
カレンダー
04 2024/05 06
S M T W T F S
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
フリーエリア
最新コメント
最新トラックバック
プロフィール
HN:
一乗寺 又兵衛
性別:
男性
職業:
コンパイル
趣味:
コンパイル
バーコード
ブログ内検索