2010-07-15 27 views
9

Tôi có một lớp (MyClass) thừa kế hầu hết các chức năng của nó từ đối tượng tích hợp Qt (QGraphicsTextItem). QGraphicsTextItem kế thừa gián tiếp từ QObject. MyClass cũng triển khai giao diện, MyInterface.Sử dụng tín hiệu Qt và các khe có nhiều thừa kế

class MyClass : public QGraphicsTextItem, public MyInterface 

tôi cần để có thể sử dụng connectdisconnect trên MyInterface*. Nhưng có vẻ như connectdisconnect chỉ hoạt động trên QObject* trường hợp. Vì Qt không hỗ trợ đa thừa kế từ các lớp dẫn xuất QObject, tôi không thể lấy được MyInterface từ QObject. (Tuy nhiên, cũng không có ý nghĩa gì đối với giao diện.)

discussion of the problem online, nhưng IMO giải pháp được đề xuất là khá vô dụng trong trường hợp thông thường (truy cập một đối tượng thông qua giao diện của nó), vì bạn không thể kết nối các tín hiệu và các khe từ MyInterface* nhưng phải đặt nó vào loại có nguồn gốc. Vì MyClass là một trong số nhiều lớp học MyInterface -derived, điều này sẽ đòi hỏi phải có "mã-smelly" nếu-này-cast-to-này-else-nếu-đó-cast-to-rằng phát biểu và đánh bại mục đích của giao diện.

Có giải pháp tốt cho giới hạn này không?

UPDATE: tôi nhận thấy rằng nếu tôi dynamic_cast một MyInterface*-QObject* (vì tôi biết tất cả MyInterface lớp -derived cũng kế thừa cuối cùng từ QObject, có vẻ như để làm việc Đó là:.

MyInterface *my_interface_instance = GetInstance(); 
connect(dynamic_cast<QObject*>(my_interface_instance), SIGNAL(MyInterfaceSignal()), this, SLOT(TempSlot())); 

Nhưng điều này thực sự có vẻ như tôi đang yêu cầu hành vi không xác định ....

+0

Bạn đã khai báo MyInterfaceSignal ở đâu và ở đâu? –

+0

'MyInterfaceSignal' được khai báo là phương thức ảo thuần túy được bảo vệ * không có tín hiệu * trong' MyInterface', và sau đó là tín hiệu * trong các lớp dẫn xuất. Do đó, trình biên dịch đảm bảo rằng các lớp dẫn xuất có phương thức, nhưng nó tùy thuộc vào người triển khai để đánh dấu nó như một tín hiệu. Đó là hokey, bởi vì tôi không * thực sự * gọi lên bảng gọi ảo từ 'MyInterface.MyInterfaceSignal', nhưng đúng hơn là dựa vào thực tế là macro SIGNAL là - vào cuối ngày - chỉ giải quyết cho một' char * 'tên phương thức. –

Trả lời

12

Bạn tìm thấy câu trả lời cho mình: các dynamic_cast hoạt động như Bạn mong chờ. Nó không phải là hành vi không xác định. Nếu instance của MyInterface bạn nhận được không phải là QObject, cast sẽ trả về null và bạn có thể tự bảo vệ mình chống lại điều đó (điều này sẽ không xảy ra, vì bạn đã nói tất cả các instance của interface cũng là QObjects). Tuy nhiên, hãy nhớ rằng bạn cần bật RTTI để nó hoạt động.

Tôi cũng xin đưa ra một vài gợi ý khác:

  • Sử dụng Q_INTERFACES tính năng (nó không chỉ cho các plug-ins). Sau đó, bạn sẽ làm việc trong điều khoản của QObject và truy vấn cho MyInterface sử dụng qobject_cast khi nó thực sự là cần thiết. Tôi không biết vấn đề của bạn một cách chi tiết, nhưng vì bạn biết rằng tất cả các cá thể MyInterface cũng là QObject, đây có vẻ là cách tiếp cận hợp lý nhất.

  • Thêm phương thức trừu tượng QObject* asQObject() vào MyInterface và triển khai dưới dạng { return this; } trong tất cả các lớp con.

  • một QGraphicsTextItem (thành phần) thay vì một (thừa kế).

6

Bạn có thể khai báo MyInterface mà ta KES một QObject trong constructor của nó:

class MyInterface { 
public: 
       MyInterface(QObject * object); 
    QObject * object() { return m_object; } 
    ... 
private: 
    QObject * m_object; 
}; 

MyInterface::MyInterface(QObject * object) : 
    m_object(object) 
{ 
    ... 
} 

Sau đó, trong MyClass constructor:

MyClass::MyClass() : 
MyInterface(this) 
{ 
    ... 
} 

Và bạn có thể kết nối tín hiệu:

MyInterface *my_interface_instance = GetInstance(); 
connect(my_interface_instance->object(), SIGNAL(MyInterfaceSignal()), this, SLOT(TempSlot())); 
Các vấn đề liên quan