2008-10-06 40 views
14

Trong C++ Style Guide Google, có một phần về Operator Overloading rằng có một tuyên bố tò mò:"Bạn không thể chuyển tiếp các lớp khai báo mà toán tử quá tải &"?

quá tải cũng có gì đáng ngạc nhiên nhánh. Ví dụ: bạn không thể các lớp khai báo chuyển tiếp quá tải operator&.

Điều này có vẻ không chính xác và tôi chưa thể tìm thấy bất kỳ mã nào khiến GCC gặp sự cố với nó. Có ai biết tuyên bố đó đang đề cập đến điều gì không?

Trả lời

20

5.3.1 của tiêu chuẩn có "Địa chỉ của một đối tượng không đầy đủ có thể được lấy, nhưng nếu kiểu hoàn chỉnh của đối tượng đó là kiểu lớp khai báo toán tử &() như một hàm thành viên, thì hành vi không xác định (và không có chẩn đoán bắt buộc)."

Tôi không biết điều này, nhưng như một áp phích khác đã chỉ ra, thật dễ dàng để xem làm thế nào nó có thể gây ra một trình biên dịch để tạo ra mã không chính xác.

0

Edited để giải thích cho nhận xét:

Đây là một đoán, nhưng một trong những lý do chính để chuyển tiếp khai báo là để có thể khai báo con trỏ tới lớp đó. Trình biên dịch phải đưa ra các giả định về lớp trước khi có định nghĩa - ví dụ, kích thước của con trỏ.

Có thể thay đổi kích cỡ của T * bằng toán tử quá tải & cho T không? (EDIT: Bình luận - và tôi nghĩ là không) - nhưng

Giả thiết bị vi phạm bởi toán tử quá tải & - làm thế nào để thay đổi lớp học?

Đây là một cách.

tôi có thể viết:

class A; 

void f(A& x) { 
    A* xPointer = &x; 
} 

Đó có một ý nghĩa mới nếu điều hành &() bị quá tải hơn nếu không muốn nói, và trình biên dịch có thể nghĩ rằng nó có thể tạo mã cho nó, nhưng nó sẽ là sai lầm.

+0

Kích thước của một con trỏ sẽ giống nhau bất kể, phải không? –

+0

Tôi tin rằng con trỏ luôn có cùng kích thước (đó là lý do tại sao trình biên dịch có thể giả định kích thước ..) ngoại trừ trường hợp con trỏ tới hàm thành viên, không thực sự là "con trỏ" theo nghĩa truyền thống. –

+0

Vâng, tôi nghĩ vậy - Tôi chỉ đang cố gắng bắt đầu từ tiền đề rằng điểm tuyên bố một loại là để trình biên dịch có thể bắt đầu đưa ra một số giả định về nó mà không cần khai báo đầy đủ. Giả định nào bị vi phạm bởi có toán tử &. –

16

tôi đã không nghe nói về nó cả, nhưng điều này sẽ cho kết quả có khả năng gây nhầm lẫn cho cùng mã trước và sau khi quá tải:

#include <iostream> 

class Foo; 

void bar (Foo& foo) { 
    std::cout << &foo << std::endl; 
} 

class Foo { 
public: 
    bool operator &() { return true; } 
}; 

void baz (Foo& foo) { 
    std::cout << &foo << std::endl; 
} 

int main() { 
    Foo foo; 

    bar(foo); 
    baz(foo); 

    return 0; 
} 

đầu ra:

0x7fff092c55df 
1 

Mặc dù có những lý do khác tại sao bạn sẽ không làm điều đó anyway - quá tải địa chỉ của không chơi độc đáo với mã stl hoặc nhiều chung chung.

+0

Giờ đây thú vị và có ý nghĩa. Có lẽ nó không phải là "không được phép" theo tiêu chuẩn, nhưng thay vào đó có kết quả không đáng tin cậy tùy thuộc vào nếu định nghĩa của lớp/struct được cung cấp chưa. –

+1

+1 cho mã mẫu thể hiện sự cố – Bill

6

Tôi nghĩ rằng tuyên bố không chính xác. Giống như các câu trả lời khác, tôi đoán ở đây. Trước tiên, tôi giả sử họ đang đề cập đến unary operator& and not binary operator&. Đó là:

int x = 5; 
int* p = &x; // unary & 
if (x & 1) // binary & 

Bạn có thể chuyển tiếp khai báo bất kỳ lớp nào bạn muốn. Tuy nhiên, nếu lớp quá tải toán tử đơn nhất & và bạn gọi toán tử & trên con trỏ đến một trong các đối tượng đó, bạn sẽ nhận được hành vi không nhất quán (đôi khi bạn chỉ cần nhận địa chỉ và đôi khi bạn sẽ gọi phương thức quá tải)). Điều này có thể dễ dàng biến thành một thứ gần như không thể gỡ lỗi.


Tôi rất vui vì người thực sự đã xem xét tiêu chuẩn và không chỉ đoán.

+1

Như được chỉ ra bởi fizzer, đó là hành vi không xác định. Không bao giờ tốt. –

0

Từ ngữ không rõ ràng, bạn dĩ nhiên có thể khai báo lớp - nhưng quy tắc rõ ràng là lấy vị trí mà bạn "không nên" nơi lớp quá tải operator&.

Các quy tắc tương tự cũng có trong các tiêu chuẩn mã hóa khác, ví dụ: JSF(pdf) quy tắc 159 nêu rõ rằng không nên quá tải các trường hợp operator&.

1

Do khả năng quá tải nhà điều hành & thư viện tăng cung cấp handy template addressof() để quản lý việc tìm địa chỉ thực của một lớp học. Không phải là tôi đề nghị bạn quá tải nhà điều hành &, nhưng nếu bạn cần, trợ giúp có sẵn.

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