C++の基礎:クラスの多重継承の曖昧さを学ぶ
概要
オブジェクト指向プログラミングとは、データ(オブジェクトの属性やプロパティ)やコードブロック(オブジェクトのメソッドや関数)を含むオブジェクトを統合する方法です。これらの属性やメソッドは、クラスに属する変数や関数であり、一般的には「クラスメンバ」と呼ばれています。C++では、クラスにはメンバ(属性、メソッド)があり、このクラス内の各メンバーを保護する必要があります。
継承は、クラスの他の機能と同様に、オブジェクト指向C++プログラミングにおける最も重要な概念の一つです。継承することで、あるクラスを別のクラスの観点から定義することができ、アプリケーションの作成や保守が容易になります。また、コードの機能を再利用することができ、実装時間を短縮することができます。継承は、クラス間の関係を実装する方法です。(例えば、長方形は形状の一種であり、楕円も形状の一種です。)
多重継承は、C++のもう一つの特徴で、一つのクラスが複数のクラスを継承することができます。例えば、派生クラスは、複数の基底クラスや派生クラスから継承することができます。
多重継承の最も顕著なエラーとして関数のオーバーライド時に発生する曖昧なエラーがあります。多重継承における曖昧さの問題を解決する方法を知りたいですか?この質問は、クラスメソッドの曖昧さの問題を解決する方法と同じです。
これを説明するために、例を挙げましょう。2つの基底クラス(AnimalとWing)があり、派生クラスでオーバーライドされていない同じ名前のinfo関数を持っているとします。派生クラスのオブジェクトを使用してこのinfo関数を呼び出そうとすると、コンパイラは曖昧であると判断し、エラーを表示します。この理由は、2つの同じ名前が衝突しており、コンパイラがどちらから継承した関数を呼び出せば良いか分からなくなっているためです。
例えば、以下のコード例を見てみましょう。
#include <iostream>
class Animal // Base Class 1
{
public:
int weight;
void info()
{
std::cout << "Weight:" << weight << "cm\n";
}
};
class Wing // Base Class 2
{
public:
int wingwidth;
void info()
{
std::cout << "Wing width:" << wingwidth << "cm\n";
}
};
class Bird: public Animal, public Wing // Derived Class 2
{
};
int main()
{
Bird eagle;
eagle.weight = 3; // in kgf
eagle.wingwidth = 280; // in cm
eagle.info();
getchar();
return 0;
}
上記のコードをC++コンパイラでビルドする、以下のようなコンパイルエラーが発生します。
[bcc32c エラー] File1.cpp(44): member 'info' found in multiple base classes of different types
File1.cpp(19): member found by ambiguous name lookup
File1.cpp(29): member found by ambiguous name lookup
C++では、同じ関数名を異なるクラスで使用することができますが、多重継承でこのエラーを回避するためには、 以下の例のように:: 演算子を使用してクラス名を明示的に指定する必要があります。
eagle.Wing::info();
eagle.Animal::info();
そのため、多重継承では2つの異なる基底クラスのinfo関数(メソッド)の両方を使用することができます。以下は具体的なコード例です。
#include <iostream>
class Animal // Base Class 1
{
public:
int weight;
void info()
{
std::cout << "Weight:" << weight << "cm\n";
}
};
class Wing // Base Class 2
{
public:
int wingwidth;
void info()
{
std::cout << "Wing width:" << wingwidth << "cm\n";
}
};
class Bird: public Animal, public Wing // Derived Class 2
{
};
int main()
{
Bird eagle;
eagle.weight = 3; // in kgf
eagle.wingwidth = 280; // in cm
eagle.Wing::info();
eagle.Animal::info();
getchar();
return 0;
}