2010-05-08 35 views
6

Kịch bản tạo ra điều này khá phức tạp vì vậy tôi sẽ loại bỏ một vài phần và đưa ra một biểu diễn chính xác về các lớp liên quan.C++ Nhiều câu hỏi thừa kế

/* This is inherited using SI by many classes, as normal */ 
class IBase 
{ 
virtual string toString()=0; 
}; 

/* Base2 can't inherit IBase due to other methods on IBase which aren't appropriate */ 
class Base2 
{ 
string toString() 
{ 
    ... 
} 
}; 

/* a special class, is this valid? */ 
class Class1 : public IBase, public Base2 
{ 
}; 

Vì vậy, điều này có hợp lệ không? Sẽ có xung đột trên toString? Hoặc Class1 có thể sử dụng Base2 :: toString để thỏa mãn IBase? Giống như tôi nói có rất nhiều thứ khác không được hiển thị, vì vậy những gợi ý cho những thay đổi lớn về thiết kế trong ví dụ này có lẽ không hữu ích ... mặc dù có đề xuất/lời khuyên chung.

suy nghĩ khác của tôi là một cái gì đó như thế này:

class Class1 : public IBase, public Base2 
{ 
virtual string toString() 
{ 
    return Base2::toString(); 
} 
}; 

này được xây dựng và liên kết, nhưng tôi không có ý tưởng nếu nó đã ẩn lỗi.

Trả lời

2

Bạn có thể sửa lỗi này bằng cách sử dụng "thừa kế ảo".

Hãy cân nhắc tạo một lớp cơ sở phổ biến mà chỉ định nghĩa một phương pháp tinh khiết ảo toString (hoặc, trong thực tế, tinh khiết phiên bản ảo của bất cứ phương pháp nó có ý nghĩa cho cả IBaseBase2 có), ví dụ

class Stringable { 
    public: 
    virtual string toString() = 0; 
}; 

Sau đó, có cả IBaseBase2 kế thừa từ lớp này Stringable:

class IBase : public Stringable 
{ 
}; 

class Base2 : public Stringable 
{ 
public: 
    virtual string toString() 
    { ... } 
}; 

Bây giờ điều này vì nó vẫn sẽ không làm việc vì Class1 sẽ có được thừa kế hai bản sao của các cơ sở Stringable lớp học, chỉ một trong số đó có một thực hiện cho toString trong hệ thống phân cấp thừa kế của nó. Điều này được gọi là "dreaded diamond". Tuy nhiên, nếu IBaseBase2 đã kế thừa hầu từ Stringable, như thế này:

class IBase : virtual public Stringable 
{ 
}; 

class Base2 : virtual public Stringable 
{ 
public: 
    virtual string toString() 
    { ... } 
}; 

Sau đó, điều này nói với trình biên dịch mà chỉ nên là một lớp Stringable cơ sở chung ngay cả khi IBaseBase2 đều thừa hưởng bởi một lớp học, đó là chính xác những gì bạn muốn, bởi vì sau đó Base2::toString được sử dụng cho Class1.

Ý tưởng thứ hai của bạn không có "lỗi ẩn", nhưng phần nào là một nỗi đau ở mông để thực hiện nhiều lần, như bạn có thể nhận ra.

1

Điều này sẽ hoạt động tốt.

Bạn đang ghi đè đúng giao diện IBase để cung cấp định nghĩa ToString() sẽ bị hủy bỏ lên đến Base2::ToString().

Lưu ý rằng Base2 không khai báo toString() là ảo, vì vậy Class1 không thể ghi đè hành vi của Base2::ToString. Không mơ hồ ở đó.

Và, ngoài ra, đây không phải là vấn đề kim cương cổ điển trong đa thừa kế được giải quyết bởi virtual inheritance vì chúng không chia sẻ một lớp cơ sở.