Các lớp cơsởảo 5.1. Một lớpcơsở xuất hiện nhiều lần trong lớp dẫn xuất Một điều hiển nhiên là không thể khai báo 2 lần cùng một lớp trong danh sách của cáclớpcơsở cho một lớp dẫn xuất. Chẳng hạn ví dụ sau là không cho phép: class B : public A, public A { } ; Tuy nhiên vẫn có thể có trường hợp cùng một lớpcơsở được đề cập nhiều hơn một lần trong cáclớpcơsở trung gian của một lớp dẫn xuất. Ví dụ: #include <iostream.h> class A { public: int a; } ; class B : public A { public: int b; } ; class C : public A { public: int c; } ; class D : public B , public C { public: int d; } ; void main() { D h ; h.d = 4 ; // tốt h.c = 3 ; // tốt h.b = 2 ; // tốt h.a = 1 ; // lỗi } Trong ví dụ này A là cơsở cho cả 2 lớpcơsở trực tiếp của D là B và C. Nói cách khác có 2 lớpcơsở A cho lớp D. Vì vậy trong câu lệnh: h.a = 1 ; thì Chương trình dịch C++ không thể nhận biết được thuộc tính a thừa kế thông qua B hay thông qua C và nó sẽ đưa ra thông báo lỗi sau: Member is ambiguous: ‘A::a’ and ‘A::a’ 5.2. Các lớp cơsởảo Giải pháp cho vấn đề nói trên là khai báo A như một lớpcơsở kiểu virtual cho cả B và C. Khi đó B và C được định nghĩa như sau: class B : virtual public A { public: int b; } ; class C : virtual public A { public: int c; } ; Các lớp cơsởảo (virtual) sẽ được kết hợp để tạo một lớpcơsở duy nhất cho bất kỳ lớp nào dẫn xuất từ chúng. Trong ví dụ trên, hai lớpcơsở A ( A là cơsở của B và A là cơsở của C) sẽ kết hợp lại để trở thành một lớpcơsở A duy nhất cho bất kỳ lớp dẫn xuất nào từ B và C. Như vậy bây giờ D sẽ chỉ có một lớpcơsở A duy nhất, do đó phép gán: h.a = 1 ; sẽ gán 1 cho thuộc tính a của lớpcơsở A duy nhất mà D kế thừa. 261 262 . c; } ; Các lớp cơ sở ảo (virtual) sẽ được kết hợp để tạo một lớp cơ sở duy nhất cho bất kỳ lớp nào dẫn xuất từ chúng. Trong ví dụ trên, hai lớp cơ sở A (. ; // lỗi } Trong ví dụ này A là cơ sở cho cả 2 lớp cơ sở trực tiếp của D là B và C. Nói cách khác có 2 lớp cơ sở A cho lớp D. Vì vậy trong câu lệnh: h.a