2010-05-25 43 views
5

Tôi đang cố gắng cấu trúc lại một số mã trong khi vẫn giữ nguyên chức năng hiện tại. Tôi gặp sự cố khi truyền một con trỏ tới một đối tượng vào một giao diện cơ sở và sau đó nhận được lớp dẫn xuất sau này. Chương trình sử dụng một đối tượng nhà máy để tạo ra các thể hiện của các đối tượng này trong một số trường hợp nhất định.Không thể truyền một lớp có nhiều thừa kế

Dưới đây là một số ví dụ về các lớp tôi đang làm việc.

// This is the one I'm working with now that is causing all the trouble. 
// Some, but not all methods in NewAbstract and OldAbstract overlap, so I 
// used virtual inheritance. 
class MyObject : virtual public NewAbstract, virtual public OldAbstract { ... } 

// This is what it looked like before 
class MyObject : public OldAbstract { ... } 

// This is an example of most other classes that use the base interface 
class NormalObject : public ISerializable 

// The two abstract classes. They inherit from the same object. 
class NewAbstract : public ISerializable { ... } 
class OldAbstract : public ISerializable { ... } 

// A factory object used to create instances of ISerializable objects. 
template<class T> class Factory 
{ 
public: 
    ... 
    virtual ISerializable* createObject() const 
    { 
     return static_cast<ISerializable*>(new T()); // current factory code 
    } 
    ... 
} 

This question có thông tin tốt về các loại đúc khác nhau, nhưng nó không giúp tôi tìm ra tình huống này. Sử dụng static_cast và truyền thường xuyên cho tôi error C2594: 'static_cast': ambiguous conversions from 'MyObject *' to 'ISerializable *'. Sử dụng dynamic_cast gây ra createObject() để trả về NULL. Các lớp kiểu NormalObject và phiên bản cũ của MyObject làm việc với static_cast hiện có trong nhà máy.

Có cách nào để làm cho dàn diễn viên này hoạt động không? Có vẻ như nó sẽ là có thể.

Trả lời

10

Bạn phải hầu như kế thừa từ ISerializable (Tôi vừa thử nghiệm nó với VS2010). Đây là vấn đề phổ biến được gọi là Vấn đề về kim cương, nơi trình biên dịch không biết đường dẫn phân cấp cần thực hiện.

EDIT:

này nên làm điều đó:

class NewAbstract : public virtual ISerializable { ... } 
class OldAbstract : public virtual ISerializable { ... } 
+0

+1: Điều này cũng làm việc trên gcc. – Troubadour

+3

Giải pháp chính xác mà Câu hỏi thường gặp đề xuất: http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.8 –

+0

Điều này giải quyết được.Tôi đã không nhận ra những tóm tắt là những thứ cần thiết để kế thừa. @Mark Ransom, cảm ơn vì liên kết tuyệt vời. Toàn bộ trang đó rất hữu ích. –

-2

Tra cứu "kim cương đáng sợ" và thừa kế ảo. Họ có thể giúp bạn.

+0

Tôi đã đưa ra +1 này nếu nó bao gồm liên kết. –

+2

Câu trả lời ở đây không phải là để đưa ra câu trả lời chính xác cho một câu hỏi cụ thể, nhưng về việc cho người đăng một hướng để nghiên cứu câu trả lời để sau đó tìm hiểu thêm và có thể trả lời nó vào lần sau. Tại sao cung cấp một liên kết khi có quá nhiều thứ có thể hữu ích? Có thể một cái gì đó như thế này: http://tinyurl.com/2cermbg? Có vẻ như thô lỗ và vô dụng. –

+0

Thật tệ khi bạn không thể đăng trực tiếp các liên kết lmtgfy tại đây. ;) –

0

Không kế thừa hầu như từ cả NewAbstract và OldAbstract. Chọn một để kế thừa hầu như từ. Tôi nghĩ rằng có thể chăm sóc nó.

+2

Không được kế thừa từ một trong số chúng - chúng hầu như kế thừa từ lớp cơ sở chung ('ISerialiazable'). –

1

Bạn có thể lấy vòng nó bằng cách đúc đến một trong các căn cứ trước mắt của bạn đầu tiên ví dụ.

virtual ISerializable* createObject() const 
{ 
    NewAbstract*const na = dynamic_cast< NewAbstract* >(new T()); 
    return dynamic_cast< ISerializable* >(na); 
} 
+0

Có vẻ như điều này có thể hoạt động. Mặc dù từ những thứ khác tôi đã đọc ở đây, có vẻ như bạn phải thực sự cẩn thận với điều này, tùy thuộc vào căn cứ. Trong mọi trường hợp, đối với vấn đề cụ thể này, NewAbstract không phải là thứ mà đối tượng nhà máy cần biết. –

+0

@Jay: Vâng, khi tôi nhìn thấy câu trả lời của Simon, tôi nhận ra rằng đó là điều đúng đắn để làm. Tôi đã bỏ lỡ sự kiện thừa kế ảo ở sai chỗ. Tôi không thích xóa một câu trả lời ngay cả khi nó là rác rưởi vì vậy tôi đã để nó ở đây để yếu đuối ...;) – Troubadour

Các vấn đề liên quan