ホーム » 2013 » 5月 » 25

日別アーカイブ: 2013年5月25日

2013年5月
« 4月   6月 »
 1234
567891011
12131415161718
19202122232425
262728293031  

最近の投稿(電子情報)

アーカイブ

カテゴリー

派生・継承と仮想関数

隠蔽化の演習を終え、次のオブジェクト指向のステップとして、 派生と継承を説明した。 簡単に仮想関数についても、実演してみた。

基本的なデータに対して、新しく機能を追加したデータを作る場合には、 C言語であれば、基本データ構造におまけデータ部をつけた新しい構造体を 宣言することになる。しかしこの方法では、新しいオマケつきデータが 発生するたびごとに、簡単な処理でも新たな関数を定義しなければならない。

そこで、オマケ付きデータも、同じように使うために派生と継承がある。 新しいオマケを加えたデータ構造をあたらしく作ることを派生と呼ぶ。 元々の基本的データ構造は、一般的に基底クラスと呼び、 追加データを加えたデータ構造は、派生クラスと呼ぶ。 派生クラスでは、基本となるデータ構造の要素やメソッドを使うことができ、 データや処理を流用できることを継承と呼ぶ。

#include
#include
#include
using namespace std ;
class Person {
private:
char name[ 20 ] ;
int age ;
public:
Person( char*n , int a ) {
strcpy( name , n ) ;
age = a ;
}
void print() {
cout << name << "'s age is " << age << endl ;
}
} ;
class Student : public Person {
private:
char school[ 20 ] ;
public:
Student( char *n , int a , char* s )
: Person( n , a )
{
strcpy( school , s ) ;
}
} ;
int main() {
Person  saitoh( "t-saitoh" , 48 ) ;
Student aoyama( "aoyama" , 21 , "fnct" ) ;
saitoh.print() ;
aoyama.print() ; // 継承で表示
return 0 ;
}
struct Student : public Person {
:
// 派生クラスで同じメソッドを新しく作っても良い
void print() {
Person::print() ; // 基底クラスのprint() を明示して呼び出し
cout << "School is " << school << endl ;
}
}
int main() {
:
// table[] には、基底クラスは同じだけど異なる型が入ってる。
Person* table[ 2 ] = { &saitoh , &aoyama } ;
for( int i = 0 ; i < 2 ; i++ )
table[ i ]->print() ;
return 0 ;
}

この例では、table[i]には、異なる型を代入できている。 しかし、table[i]->print() では、table[1]において、"School is fnct"は 表示されない。 あくまで、table[] に代入する際に、Student型がPerson型に 格下げされている。

table[1]には、Student 型が入っているのだから、"School is fnct"を表示して欲しい場合には どうすればよいのか、こういう時は仮想関数を用いる。 仮想関数では、関数の前に virtual を付加する。

class Person {
:
virtual void print() {
cout << name << "'s age is " << age << endl ;
}
} ;
class Student : public Person {
:
virtual void print() {
Person::print() ;
cout << "School is " << school << endl ;
}
} ;

この様に宣言すると、データ生成時にそれぞれのオブジェクトには、 型を識別する情報が付けられる。 仮想関数を呼び出す時には、データ種別情報を元に、型に応じたメソッドが呼び出される。