C++編で扱っている C++ は 2003年に登場した C++03 という、とても古いバージョンのものです。C++ はその後、C++11 -> C++14 -> C++17 -> C++20 -> C++23 と更新されています。
なかでも C++11 での更新は非常に大きなものであり、これから C++ の学習を始めるのなら、C++11 よりも古いバージョンを対象にするべきではありません。特に事情がないなら、新しい C++ を学んでください。 当サイトでは、C++14 をベースにした新C++編を作成中です。
問題① 「飛ぶ (Fly)」という動作に注目して、「鳥 (Bird)」のクラスを定義してください。
#include <iostream>
#include <vector>
// 鳥の抽象クラス
class Bird {
public:
virtual ~Bird() {}
virtual void Fly() = 0;
};
// 鷹
class Hawk : public Bird {
public:
virtual void Fly()
{
std::cout << "flying hawk" << std::endl;
}
};
// ツバメ
class Swallow : public Bird {
public:
virtual void Fly()
{
std::cout << "flying swallow" << std::endl;
}
};
// ペンギン
class Penguin : public Bird {
public:
virtual void Fly()
{
std::cout << "penguins can't fly" << std::endl;
}
};
int main()
{
typedef std::vector<Bird*> BirdContainer;
;
BirdContainer birds.push_back(new Hawk());
birds.push_back(new Swallow());
birds.push_back(new Penguin());
birds
const BirdContainer::iterator itEnd = birds.end();
for (BirdContainer::iterator it = birds.begin(); it != itEnd; ++it) {
(*it)->Fly();
}
for (BirdContainer::iterator it = birds.begin(); it != itEnd; ++it) {
delete *it;
}
}
実行結果:
flying hawk
flying swallow
penguins can't fly
「鳥」という言葉には、具体的な鳥の種類が想定されていませんから、抽象クラス📘として設計するのは、適切な考え方です。具体的な鳥の種類を想定するのは、派生クラス📘の役割です。
ちなみに、飛べない鳥であるペンギンを、鳥のクラスから派生して定義することは、場合によっては問題のある設計になるかもしれません。Flyメンバ関数を呼びだしたら、対象のオブジェクトが「飛ぶ」ことを期待しているのなら、Penguin::Flyメンバ関数は、何らかの手段でプログラムを停止させるなり、エラーを出すなりすべきでしょう。
問題② 「飛ぶ (Fly)」という動作は、鳥だけでなく、飛行機などにも適用できます。そのような観点で、インターフェースを設計してください。
#include <iostream>
#include <vector>
// 「飛べるもの」を表すインターフェース
class IFly {
public:
virtual ~IFly() {}
virtual void Fly() = 0;
};
// 鷹
class Hawk : public IFly {
public:
virtual void Fly()
{
std::cout << "flying hawk" << std::endl;
}
};
// ツバメ
class Swallow : public IFly {
public:
virtual void Fly()
{
std::cout << "flying swallow" << std::endl;
}
};
// 飛行機
class Airplane : public IFly {
public:
virtual void Fly()
{
std::cout << "flying airplane" << std::endl;
}
};
int main()
{
typedef std::vector<IFly*> FlyObjectContainer;
;
FlyObjectContainer flyObjects.push_back(new Hawk());
flyObjects.push_back(new Swallow());
flyObjects.push_back(new Airplane());
flyObjects
const FlyObjectContainer::iterator itEnd = flyObjects.end();
for (FlyObjectContainer::iterator it = flyObjects.begin(); it != itEnd; ++it) {
(*it)->Fly();
}
for (FlyObjectContainer::iterator it = flyObjects.begin(); it != itEnd; ++it) {
delete *it;
}
}
実行結果:
flying hawk
flying swallow
flying airplane
基本的な形は、抽象クラスの場合と変わりませんが、派生クラスが、「鳥」と is-a関係で結ばれる必要はなくなったので、「飛ぶことができる」のであれば、何でも派生してよくなりました。そのため、「飛行機」を派生できますが、一方で、飛ぶことができない「ペンギン」を派生することは、明確に誤っていることになります。
Programming Place Plus のトップページへ
はてなブックマーク に保存 | Pocket に保存 | Facebook でシェア |
X で ポスト/フォロー | LINE で送る | noteで書く |
![]() |
管理者情報 | プライバシーポリシー |