新規記事の投稿を行うことで、非表示にすることが可能です。
2017年12月30日
《その213》 クロスキャスト(1)
クロスキャスト
下記のプログラムの説明を通して、クロスキャストの働きを確認したいと思います。
抽象クラス Singer は、
データメンバ name、
純粋仮想デストラクタ ~Singer、
それと、
純粋仮想関数 sing, 関数perform を持っています。
sing は歌う関数です。
(実際には "歌声 ♪" のようなテキストが表示されるだけですが (;^ω^A )
perform は、挨拶してから歌う関数です。
抽象クラス Player は、
純粋仮想デストラクタ ~Player と
関数 play
だけで構成されています。
play は演奏する関数です。
(実際には "演奏 ♪" のようなテキストが表示されるだけですが (;^ω^A )
play の演奏音は、"演奏 ♪ ♪ ♪" です。
Singer_typeAクラスは、クラス Singer の public派生です。
コンストラクタでデータメンバ name を設定します。そして、
関数 sing の歌声を定義します。
sing の歌声は、 "歌声 ♪♪♪♪♪" です。
Singer_typeBクラスは、多重継承クラスです。
クラス Singer,クラス Player の2つから public派生しています。
コンストラクタでデータメンバ name を設定します。そして、
関数 sing の歌声を定義します。
sing の歌声は "歌声 ♪ ♪ ♪" で、Singer_typeA の sing とは少し違っています。
main関数では、
Singer_typeA の asano と tohno、
Singer_typeB の michi と nakai の4人を定義しています。
そして、Singer*型のポインタ a[i] で4人を指し、
a[i]->perform();
として、動的に 関数 perform を呼び出しています。その結果、
Singer_typeA の2人の歌は、"歌声 ♪♪♪♪♪"
Singer_typeB の2人の歌は、"歌声 ♪ ♪ ♪" となっています。
クラス Player の資産を継承している Singer_typeB の2人は、歌だけでなく演奏もできるのですが、Singer*型のポインタで指されているので、クラス Singer の資産しか使えず、演奏できません。
そこで、クロスキャスト
dynamic_cast<Player*>(a[i])
を試しています。Singer*型から Player*型へのキャストです。
キャストに失敗すれば、空ポインタが返されますから ★ の箇所の if文は実行されません。
dynamic_cast演算子を用いると、多重継承を行った2つの親へのポインタ間のクロスキャストが成功します。
クロスキャストが成功し、得られた Player*型のポインタ p で
p->play();
とすることで、演奏させることが可能になります。
// ------------------------------------
#include <string>
#include <iostream>
class Singer {
protected:
std::string name;
public:
Singer(std::string str) : name(str) { }
virtual ~Singer() = 0;
virtual void sing() const = 0;
void perform() const {
std::cout << name << "です! よろしく。\n";
sing();
}
};
Singer::~Singer() { }
class Player {
public:
virtual ~Player() = 0;
void play() {
std::cout << "演奏 ♪ ♪ ♪\n";
}
};
Player::~Player() { }
class Singer_typeA : public Singer {
public:
Singer_typeA(std::string str) : Singer(str) { }
void sing() const {
std::cout << "歌声 ♪♪♪♪♪\n";
}
};
class Singer_typeB : public Singer, public Player {
public:
Singer_typeB(std::string str) : Singer(str) { }
void sing() const {
std::cout << "歌声 ♪ ♪ ♪\n";
}
};
int main() {
Singer* a[] = {
new Singer_typeA("asano"),
new Singer_typeA("tohno"),
new Singer_typeB("michi"),
new Singer_typeB("nakai"),
};
for (int i = 0; i < 4; i++) {
a[i]->perform();
/*★*/ if (Player* p = dynamic_cast<Player*>(a[i]))
p->play();
std::cout << '\n';
delete a[i];
}
}
// ------------------------------------