Trong C ++, một lớp có thể kế thừa (trực tiếp hoặc gián tiếp) từ nhiều hơn một lớp, được gọi là
đa kế thừa .
Tuy nhiên, C # và Java giới hạn các lớp ở mức kế thừa đơn lẻ, mỗi lớp kế thừa từ một lớp cha duy nhất.
Đa kế thừa là một cách hữu ích để tạo các lớp kết hợp các khía cạnh của hai phân cấp lớp khác nhau, điều thường xảy ra khi sử dụng các khung lớp khác nhau trong một ứng dụng.
Ví dụ: nếu hai khung công tác xác định các lớp cơ sở của riêng chúng cho các ngoại lệ, bạn có thể sử dụng đa kế thừa để tạo các lớp ngoại lệ có thể được sử dụng với một trong hai khung.
Vấn đề với đa kế thừa là nó có thể dẫn đến sự mơ hồ. Ví dụ cổ điển là khi một lớp kế thừa từ hai lớp khác, mỗi lớp kế thừa từ cùng một lớp:
class A {
protected:
bool flag;
};
class B : public A {};
class C : public A {};
class D : public B, public C {
public:
void setFlag( bool nflag ){
flag = nflag; // ambiguous
}
};
Trong ví dụ này, flag
thành viên dữ liệu được xác định bởi class A
. Nhưng class D
giảm dần từ class B
và class C
, cả hai đều bắt nguồn từ A
, vì vậy về bản chất, hai bản sao của flag
có sẵn vì hai thể hiện của A
nằm trong D
hệ thống phân cấp lớp của. Bạn muốn đặt cái nào? Trình biên dịch sẽ phàn nàn rằng tham chiếu đến flag
in D
là không rõ ràng . Một cách khắc phục là phân biệt rõ ràng tham chiếu:
B::flag = nflag;
Một cách khắc phục khác là khai báo B và C là virtual base classes
, có nghĩa là chỉ có một bản sao của A có thể tồn tại trong hệ thống phân cấp, loại bỏ mọi sự mơ hồ.
Sự phức tạp khác tồn tại với đa kế thừa, chẳng hạn như thứ tự mà các lớp cơ sở được khởi tạo khi một đối tượng dẫn xuất được xây dựng, hoặc cách các thành viên có thể vô tình bị ẩn khỏi các lớp dẫn xuất. Để tránh những phức tạp này, một số ngôn ngữ tự giới hạn mô hình kế thừa đơn giản hơn.
Mặc dù điều này làm đơn giản hóa việc kế thừa đáng kể, nhưng nó cũng hạn chế tính hữu dụng của nó vì chỉ các lớp có tổ tiên chung mới có thể chia sẻ các hành vi. Các giao diện giảm thiểu phần nào hạn chế này bằng cách cho phép các lớp trong các cấu trúc phân cấp khác nhau hiển thị các giao diện chung ngay cả khi chúng không được triển khai bằng cách chia sẻ mã.