派生クラスでさえ変更できない場合、それらが特定の型であることを知らずに GetInfo を呼び出すのは困難です。直接的な解決策を使用する必要があるかもしれません:
GradStudent gradStudent;
cout << gradStudent.GetInfo();
または、学生が指定された派生クラスであるかどうかを確認しようとすることもできますが、IMO は非常に醜く危険です (コードを拡張するという点で):
for (int i = 0; i < 3; i++)
{
GradStudent * gs = dynamic_cast<GradStudent *>(classRoom[i]);
if (gs != nullptr)
cout << gs->GetInfo();
else
{
UndergradStudent * ugs = dynamic_cast<UndergradStudent *>(classRoom[i]);
if (ugs != nullptr)
cout << ugs->GetInfo();
else
cout << classRoom[i]->GetInfo();
}
}
ポリモーフィズムは、このような状況を処理するために特別に作成されたものであり、GetInfo が基底クラスで仮想化されていないことは、重大なアーキテクチャ上の欠陥であると言わざるを得ません。
さらに: ポインターで遊んでいる場合は、ローカル変数へのアドレスを取得しないでください。それは危険かもしれません。代わりに、メモリの割り当てと割り当て解除を手動で行います。
classRoom[0] = new Student;
classRoom[1] = new GradStudent;
classRoom[2] = new UndergradStudent;
// Process data
for (int i = 0; i < 3; i++)
delete classRoom[i];
余談: 私は次のようなタスクが嫌いです: Y を使用せずに X を実行します (Y はX を解決するために特別に設計されています)。
編集:(コメントに応じて)
あなたは、仮想機能がどのように問題を解決するのかと尋ねました。少しの間、それStudent::GetInfo
が仮想であるとします。次のコードを分析してみましょう。
Student * student = new Student;
student->GetInfo(); // Student::GetInfo is called
GradStudent * gradStudent = new GradStudent;
gradStudent->GetInfo(); // GradStudent::GetInfo is called
今のところ、驚くべきことは何もありません。
Student * student = new GradStudent;
student->GetInfo();
// if Student::GetInfo is virtual, GradStudent::GetInfo is called here
// if Student::GetInfo is not virtual, Student::GetInfo is called here
今、注意深く読んでください。Student::GetInfo
仮想GradStudent
でクラスに実装されている場合はGradStudent::GetInfo
、実際には変数で呼び出されるにもかかわらず、呼び出されStudent
ます。ただし、Student::GetInfo
が virtualでない場合、前のケースでStudent::GetInfo
は が呼び出されます。これは、基本的に仮想関数がどのように機能するかです。
あなたの場合、 Student * 変数の配列があります。それらがStudent
s、GradStudent
s、またはUndergradStudent
s であるかどうかは正確にはわかりません。yourStudent::GetInfo
は仮想ではないため、これらの変数でこのメソッドを呼び出すとStudent::GetInfo
、実際の型に関係なく、常に が呼び出されます。
そのような場合、私が考えることができる唯一の解決策は、実際にどのクラスであるかを推測しようとすることです:
Student * student = new UndergradStudent;
Student * s = student; // Ok
GradStudent * gs = dynamic_cast<GradStudent *>(student); // Not true, will return NULL/nullptr
UndergradStudent * ugs = dynamic_cast<UndergradStudent *>(student); // Ok
このようにして、元の型に戻りGetInfo
、実際の変数型を呼び出すことができます。
ただし、これは醜い解決策であり、この種の問題は仮想関数によって解決されることに注意してください。
C++ FAQは、仮想関数について詳しく読むのに適した場所です。