Một vấn đề tồn tại là khi nhiều lớp cơ sở được kế thừa trực tiếp bởi một lớp dẫn xuất. Để hiểu rõ hơn vấn đề này, xét tình huống các lớp kế thừa theo sơ đồ như sau:
Hình 7. Các lớp cơ sở được kế thừa trực tiếp từ một lớp dẫn xuất
ở đây, lớp A được kế thừa bởi hai lớp B và C. Lớp D kế thừa trực tiếp cả hai lớp B và C. Như vậy lớp A được kế thừa hai lần bởi lớp D: lần thứ nhất nó được kế thừa thông qua lớp B, và lần thứ hai được kế thừa thơng qua lớp C. Bởi vì có hai bản sao của lớp A có trong lớp D nên một tham chiếu đến một thành phần của lớp A sẽ tham chiếu về lớp A được kế thừa gián tiếp thông qua lớp B hay tham chiếu về lớp A được kế thừa gián tiếp thông qua lớp C? Để giải quyết tính khơng rõ ràng này, C++ có một cơ chế mà nhờ đó chỉ có một bản sao của lớp A ở trong lớp D: đó là sử dụng lớp cơ sở ảo.
Trong ví dụ trên, C++ sử dụng từ khóa vitual để khai báo lớp A là ảo trong các lớp B và C theo mẫu như sau:
clacc B : virtual public A {...};
clacc C : virtual public A {...};
clacc D : public B, public C {...};
Việc chỉ định A là ảo trong các lớp B và C nghĩa là A sẽ chỉ xuất hiện một lần trong lớp D. Khai báo này không ảnh hưởng đến các lớp B và C.
Chú ý: Từ khóa virtual có thể đặt trước hoặc sau từ khóa public, private, protected. Ví dụ #include <iostream.h> #include <conio.h> class A { float x,y; public:
void set(float x1, float y1) A
B C
{ x = x1; y = y1; } float getx() { return x; } float gety() { return y; } };
class B : virtual public A { };
class C : virtual public A { };
class D : public B, public C { }; void main() { clrscr(); D d; cout<<"\nd.B::set(2,3)\n"; d.B::set(2,3); cout<<"\nd.C::getx() = "; cout<<d.C::getx()<<endl; cout<<"\nd.B::getx() = "; cout<<d.B::getx()<<endl; cout<<"\nd.C::gety() = "; cout<<d.C::gety()<<endl; cout<<"\nd.B::gety() = "; cout<<d.B::gety()<<endl; cout<<"\nd.C::set(2,3)\n"; d.C::set(2,3); cout<<"\nd.C::getx() = "; cout<<d.C::getx()<<endl; cout<<"\nd.B::getx() = "; cout<<d.B::getx()<<endl; cout<<"\nd.C::gety() = "; cout<<d.C::gety()<<endl; cout<<"\nd.B::gety() = "; cout<<d.B::gety()<<endl; getch(); }
Chương trình trên sẽ cho kết quả: d.B::set(2,3)
d.C::getx() = 2 d.B::getx() = 2 d.C::gety() = 3 d.B::gety() = 3
d.C::set(2,3) d.C::getx() = 2 d.B::getx() = 2 d.C::gety() = 3 d.B::gety() = 3