2011-08-25 30 views
5

Các bit mã sau biên dịch mà không cần cảnh báo cho Windows, Mac và iOS:Tại sao so sánh một con trỏ hàm thành viên với NULL tạo ra một cảnh báo?

class MyClass { 
    SomeOtherClass * m_object; 
    void (SomeOtherClass::*m_callback)(); 
public: 
    MyClass(SomeOtherClass * _object,void (SomeOtherClass::*_callback)()=NULL) : 
     m_object(_object),m_callback(_callback) {} 

    void DoStuff() { 
     //generates warning: NULL used in arithmetic when compiling with the Android NDK 
     if (NULL==m_callback) { 
      m_object->DoNormalCallback(); 
     } else { 
      (m_object->*m_callback)(); 
     } 
    } 
}; 

Tại sao cảnh báo rằng tạo ra và những gì tôi có thể làm gì về nó?

+0

Đó là phong cách tốt để so sánh mọi thứ với 'NULL', không so sánh 'NULL' với mọi thứ. Chuyển đổi thứ tự: 'if (m_callback == NULL)' –

+6

Bí quyết để viết 'if (0 == x)' để nếu bạn nhầm lẫn '==' với '=', bạn sẽ phá vỡ sự biên dịch, chứ không phải chỉ nhận được cảnh báo (hoặc không có gì). – hamstergene

+0

Một số nguyên tắc đang nói để đặt hằng số vào bên trái của phép so sánh để tránh việc gán sai. Tôi nghĩ nó không đáng giá nhưng có những ý kiến ​​khác. – Simon

Trả lời

2

Tôi không nghĩ rằng bạn được phép so sánh 0 (hoặc NULL) với các con trỏ hàm thành viên, đặc biệt vì chúng có thể không thực sự là con trỏ (ví dụ như hàm là virtual).

Cá nhân, tôi muốn viết lại bài kiểm tra if mà không có sự so sánh, ví dụ .:

void DoStuff() { 
    if (m_callback) { 
     (m_object->*m_callback)(); 
    } else { 
     m_object->DoNormalCallback(); 
    } 
} 

Và, cho điểm thưởng, thực hiện kiểm tra này int các nhà xây dựng.

class MyClass { 
    SomeOtherClass * m_object; 
    void (SomeOtherClass::*m_callback)(); 
public: 
    MyClass(SomeOtherClass * _object,void (SomeOtherClass::*_callback)()=NULL) : 
     m_object(_object),m_callback(_callback) 
    { 
     // Use "DoNormalCallback" unless some other method is requested. 
     if (!m_callback) { 
      m_callback = &SomeOtherClass::DoNormalCallback; 
     } 
    } 

    void DoStuff() { 
     (m_object->*m_callback)(); 
    } 
}; 
+0

Tại sao thực hiện thử nghiệm? Chỉ cần sử dụng '& SomeOtherClass :: DoNormalCallback' làm giá trị mặc định thay cho' NULL'. – Nemo

+0

Bạn có thể chuyển đổi hằng số con trỏ null thành kiểu con trỏ thành thành viên, xem # 4.11 của tiêu chuẩn hiện tại (không chắc chắn về C++ 03 nhưng nó sẽ giống nhau ở đó). –

4

Nếu NULL được định nghĩa là ((void*)0), bạn có thể nhận được cảnh báo. Các con trỏ đối tượng không tương thích với các con trỏ hàm. Sử dụng số đồng bằng 0 thay vì NULL. 0 là hằng số con trỏ null tương thích với cả con trỏ hàm và kiểu con trỏ đối tượng.

EDIT Xin lỗi, tôi không chú ý đúng. Có một con trỏ chức năng thành viên ở đây, không chỉ là con trỏ hàm. So sánh một với ((void*)0) cũng vi phạm các quy tắc và nhiều trình biên dịch sẽ phát hành các lỗi , không chỉ cảnh báo, về điều này.

EDIT 2 Đối với tất cả những người đã nhận xét: Tôi biết rằng trình biên dịch C++ phù hợp sẽ không xác định NULL là ((void*)0). Vấn đề là có các trình biên dịch không phù hợp và các thư viện của bên thứ ba bị hỏng trên đó (tôi đã thấy cả hai).

+0

Theo [một trang trên trang web gcc] (http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt02ch04s03.html) nó nói 'NULL' được định nghĩa là' __null', một từ khóa của gcc. –

+0

Trong C++, 'NULL' sẽ không bao giờ được định nghĩa là' ((void *) 0) '. –

+0

Trong C++ 'NULL' không thể được định nghĩa là' ((void *) 0) '. Nếu có, mã ở trên sẽ không biên dịch. – ymett

0

if (m_callback) theo đề nghị của André Caron hoạt động, nhưng tôi chưa bao giờ là một fan hâm mộ của phôi ngầm để bools và thích sử dụng một nhà điều hành mà đánh giá đến bool. Đó là một chút tiết, nhưng điều này hoạt động:

if (static_cast<void (SomeOtherClass::*)()>(NULL)==m_callback) 
    m_object->DoNormalCallback(); 
} else { 
    (m_object->*m_callback)(); 
} 

Vẫn không chắc chắn tại sao phiên bản NDK của GCC cần dàn diễn viên.

1

Hãy thử tắt cảnh báo bằng -Wno-conversion-null.

0

Trước C++ 11, kết quả so sánh con trỏ với thành viên so với '0' không xác định.

Trong C++ 11, nó là hợp pháp để so sánh con trỏ-to-thành viên so với C++ 11 từ khóa mới 'nullptr'

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