多態性

http://www.geocities.jp/ky_webid/cpp/language/009.html

継承関連で重要なものがこの多態性というものです。

簡単に言えば、サブクラス型の変数はスーパークラス型のポインタ変数に代入可能という話です。

実際に見てみましょう

#include <iostream>

class CBase {
public:
    virtual void foo ();
    void call ();
};

class CSub : public CBase {
public:
    void foo ();
};

void CBase::foo () {
    std::cout << "CBase::foo" << std::endl;
}

void CBase::call () {
    foo();
}

void CSub::foo () {
    std::cout << "CSub::foo" << std::endl;
}

int main () {
    CSub objs;
    CBase *obj = &objs;
    
    obj->call();
    
    return 0;
}
$ main
CSub::foo

CSub型とCBase型では本来型が違うので代入できる筈が無いのですが、サブクラスはスーパークラスの型を含んでいるので代入することができるとのことです。

ただし当然のことながらこの場合、呼び出せるメソッドはスーパークラス型のメンバ関数に限られます。

上記の場合、あくまでもobjポインタ変数はCBase型なのでCSubのみに定義されているメンバ関数までは関知できないので呼び出せません。

例えばCSubにしか存在しないbar関数があるとして以下のような処理を書いたらコンパイルエラーとなります。

int main () {
    CSub objs;
    CBase *obj = &objs;
    
    obj->bar();
    
    return 0;
}
$ cl /W4 /EHs main.cpp
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp
main.cpp(35) : error C2039: 'bar' : 'CBase' のメンバではありません。
        main.cpp(3) : 'CBase' の宣言を確認してください。

この多態性が本領発揮するのは記事にもあるように配列に格納されたオブジェクトに対して同じメンバ関数を呼ぶ処理が的確だと思います。

こういった処理はC言語の場合だと例えばif文などで処理わけし、それぞれ別の関数を呼び出さなければなりませんでした。

多態性を利用すれば基本のクラスから派生して処理わけをし、実際の実行は配列等でループしながらメンバ関数を呼び出すだけなのでかなり処理がスッキリすると思います。

すばらしいですね。