多重継承を行うと、基本クラスに指定したクラスの要素をすべて引き継ぐことになります。以下のような継承関係を見てみましょう。クラス derived1もderived2も同一のbaseクラスを継承しています。これらふたつのクラスを多重継承してderived3クラスを定義します。
class base {
int a;
};
class derived1 : public base {
...
};
class derived2 : public base {
...
};
class derived3 : public derived1, public derived2 {
...
};
このように作成されたderived3クラスのメモリレイアウトは以下のようになり、baseクラスのメンバが重複して含まれます。baseクラスのメンバ a にアクセスしようとしたときには、先の重複したメンバ名と同一のあいまいさが発生します。この場合には、derived1::a, derived2::a のようにスコープ解決演算子を使って、あいまいさを解消する必要があります。

基本クラスの要素が派生クラスに複数含まれてしまうのが好ましくない場合も存在します。先のStudentクラスを例にとって説明しましょう。
Studentクラスは、学生の名前、課題1、課題2の得点、平均点を管理するクラスでした。ある人はStudentを継承して課題3の得点を管理できるようにしたStudentAクラスを作成したとしましょう。また別のひとは、Studentを継承して課題4の得点を管理できるStudentBクラスを作成したとします。

ここで、課題1~4の4つの課題を管理したいStudentCクラスを作成するとします。せっかくですのですでに作成済みのStudentA,StudentBクラスを利用したいですよね。そこでStudentA、StudentBクラスを継承してStudentCクラスを作成すると・・・

このような継承関係になり、Studentクラスのメンバを重複して持ったクラスとなってしまいます。これではメモリの無駄も甚だしいですよね。このような無駄を解消し、継承階層の祖先にいる基本クラスのメンバは重複して持たないようにする機能を仮想基本クラスと呼びます。
StudentAクラスとStudentBクラスを作成するときに、以下のようにキーワード virtual を指定します。
class StudentA : virtual public Student {
private:
int kadai3;
public:
....
....
};
class StudentB : virtual public Student {
private:
int kadai4;
public:
....
....
};
このキーワードは、「これからさき誰かが僕を継承して新しいクラスを作るかもしれないけど、その時には基本クラス(Studentクラス)の要素は重複させないでね。」ということをコンパイラに示しています。この時の継承階層は以下のように表します。

仮想基本クラスの説明にあるような、StudentCクラスを定義し、動作確認できるプログラムを作成せよ。新規に p3k3_5というプロジェクトを作成し、練習問題3-1で使用したStudentクラスをプロジェクトに追加して使用すること。(student.cpp,student.hだけ使う。StudentEXクラスなどは使用しない。)また,以下の点を満たすこと.
作成したStudentCクラスの動作確認用のコードの例(main関数)を以下に示す。
#include <iostream>
using namespace std;
#include "studentC.h"
void main()
{
StudentC obj;
obj.SetName("taro");
obj.SetKadai1(90);
obj.SetKadai2(30);
obj.SetKadai3(80);
obj.SetKadai4(12);
obj.CalcAve();
cout << obj.Name() << endl;
cout << "kadai1:" << obj.GetKadai1()
<< " kadai2:" << obj.GetKadai2()
<< " kadai3:" << obj.GetKadai3()
<< " kadai4:" << obj.GetKadai4()<< endl;
cout << "ave:" << obj.Average()
<< " sum:" << obj.GetSum() << endl;
cout << "---------------------------" << endl;
//可能であれば、以下のようなコンストラクタを
//使った初期化ができるようにトライしてみよう
//StudentC obj2("jiro", 20, 40, 50, 64);
//obj2.CalcAve();
//cout << obj2.Name() << endl;
//cout << "kadai1:" << obj2.GetKadai1()
// << " kadai2:" << obj2.GetKadai2()
// << " kadai3:" << obj2.GetKadai3()
// << " kadai4:" << obj2.GetKadai4()<< endl;
//cout << "ave:" << obj2.Average()
// << " sum:" << obj2.GetSum() << endl;
}