2012-05-25 27 views
5

Tôi đã có mã này chạy khá lâu trong một thư viện:QFlags Enum Loại Chuyển đổi thất bại tất cả của một đột ngột

MyClass::MyClass() 
    : QDialog() 
{ 
    // (...) 
    setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint); 
    // (...) 
} 

Sau đó, sau khi thay đổi các phần khác nhau của thư viện, tôi nhận được tin nhắn này tất cả đột ngột:

error C2664: 'QWidget::setWindowFlags': cannot convert parameter 1 from 'int' to 'Qt::WindowFlags' 

Dường như nó không tìm thấy | toán tử quá tải được cung cấp bởi lớp QFlags để kết quả của | trả về một int chứ không phải là một cấu trúc QFlags.

Tôi biết tôi có thể truyền kết quả theo cách thủ công đến (Qt::WindowFlags) và làm cho nó hoạt động, nhưng QFlags thường sẽ làm cho loại diễn viên này không cần thiết.

Bất kỳ ý tưởng nào về loại thay đổi nào có thể dẫn đến hành vi này?

Tôi bao gồm <QtGui/QDialog> thường là đủ. Bao gồm <QtCore/QFlags> không thay đổi hành vi.

Trả lời

5

Qt đặt nhà khai thác enum của nó trong không gian tên toàn cầu thay vì trong không gian tên Qt. Nếu có một toán tử khác khớp với không gian tên hiện tại, trình biên dịch will not search the parent scopes. Ngay sau khi bạn thêm một quá tải cho một toán tử trong không gian tên của bạn, quá tải của Qt sẽ không nằm trong tập hợp các kết quả phù hợp.

Fèlix's answer below cũng là không hợp lệ vì nó sẽ đòi hỏi hai chuyển đổi ngầm: int ->QFlag ->QFlags. Visual C++ sẽ chấp nhận nó do một long-standing bug nhưng hầu hết các trình biên dịch sẽ từ chối nó:

error: no viable conversion from 'unsigned int' to 'Qt::WindowFlags' 
    (aka 'QFlags<Qt::WindowType>') 
Qt::WindowFlags f = Qt::CustomizeWindowHint | Qt::WindowTitleHint; 
       ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

này hoạt động trên tất cả các trình biên dịch:

Qt::WindowFlags f(Qt::CustomizeWindowHint | Qt::WindowTitleHint); 

bởi vì chỉ có một chuyển đổi được yêu cầu: int ->QFlag.

Giải pháp thực sự là để Qt đặt các toán tử vào cùng một không gian tên như các kiểu chúng hoạt động. Trong khi đó, bạn có thể nhập các nhà khai thác bản thân:

using ::operator|; 
setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint); 

Lưu ý rằng điều này có thể có những hậu quả ngoài ý muốn, như bạn có thể làm cho rất nhiều tên có sẵn trong một bối cảnh mà họ không nên.

Khung bế mạc vào line 1733 là kết thúc của namespace Qt đã được mở trên line 58.

ADL thường được sử dụng để giải quyết các nhà khai thác được khai báo trong namespace giống như các loại, nhưng điều này không có tác dụng nếu các nhà khai thác đang ở trong một không gian tên khác nhau.

+0

Làm cho tinh thần, cảm ơn lời giải thích chi tiết. –

0

Bạn đã cố gắng tách biệt | biểu thức từ hàm gọi? Một cái gì đó như:

// .. 
Qt::WindowFlags flags = Qt::CustomizeWindowHint | Qt::WindowTitleHint; 
setWindowFlags(flags); 
// ... 

Chỉ cần để xem nơi chính xác vấn đề là ...

Nếu đó là một vấn đề bao gồm, chỉ cần làm #include <QtGui>

+0

Nó biên soạn tốt nếu tôi chia thành hai dòng như thế. Bất kỳ ý tưởng về sự khác biệt cho mã của tôi? Có thể là toán tử =? –

+0

@ Fèlix ngoặc đơn được bỏ ghép trong ví dụ của bạn – dschulz

+0

@dschulz Cảm ơn! Lỗi của tôi! Bây giờ là ok. –

1

Kiểm tra mã nguồn của bạn để xem bạn có sử dụng Q_DECLARE_OPERATORS_FOR_FLAGS để khai báo cờ của bạn ở đâu đó trong không gian tên trước khi bạn gặp lỗi biên dịch hay không.

Như @isanae đã nói, If there is another operator that matches in the current namespace, .... Vì vậy, bạn không nên đặt toán tử khác có thể khớp.

Giải pháp là đặt tất cả khai báo Q_DECLARE_OPERATORS_FOR_FLAGS của riêng bạn trong không gian tên chung, giống như những gì Qt làm.

Hy vọng điều này có thể hữu ích. Tôi nhấn cùng một vấn đề khi tôi đặt mọi thứ vào môi trường xây dựng thống nhất, và tôi chuyển đổi thứ tự mã nguồn và cuối cùng định vị đoạn mã gây ra sự cố này: một trong Q_DECLARE_OPERATORS_FOR_FLAGS bên trong một không gian tên.

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