2012-04-19 23 views
12

Khi tôi cố gắng biên dịch như sau (g ++ 4.6.3)Quá tải toán tử C++: không biết chuyển đổi từ đối tượng sang tham chiếu?

class A {}; 

A& operator*=(A& a, const A& b) 
{ 
    return a; 
} 

A operator*(const A& a, const A& b) 
{ 
    return A(a) *= b; 
} 

int main(int, char*[]) 
{ 
    A a, b; 

    a = a*b; 

    return 0; 
} 

tôi nhận được lỗi

/tmp/test.cxx: In function ‘A operator*(const A&, const A&)’: 
/tmp/test.cxx:14:20: error: no match for ‘operator*=’ in ‘(* & a) *= b’ 
/tmp/test.cxx:14:20: note: candidate is: 
/tmp/test.cxx:6:1: note: A& operator*=(A&, const A&) 
/tmp/test.cxx:6:1: note: no known conversion for argument 1 from ‘A’ to ‘A&’ 

này câu đố tôi - làm thế nào có thể chuyển đổi từ một lớp học để một tham chiếu đến lớp không được biết?

Thay đổi việc kê khai của lớp A như sau không có bất kỳ tác dụng:

class A 
{ 
public: 
    A() {} 
    A(const A&) {} 
}; 

Cùng một lỗi.

Tôi sẽ vô cùng biết ơn vì những gợi ý về những gì đang xảy ra ở đây.

+0

Bạn có thể khắc phục vấn đề này bằng cách khai báo toán tử trong phạm vi của lớp. Sau đó, chữ ký phương thức của bạn sẽ giống như sau: 'Toán tử * (const A & rhs) const;' Nếu bạn muốn sử dụng toán tử ghép cho việc thực hiện, bạn có thể viết: 'return * this * = rhs' – Paranaix

+0

@Paranaix: Không, bạn không thể sử dụng 'operator * =' trên '* this' bên trong' const' chức năng thành viên, vì nó sẽ sửa đổi '* this'. –

+0

@BenVoigt: Vâng hoàn toàn đúng của bạn. Tôi muốn viết nó như một lớp lót và vô tình loại bỏ toàn bộ ma thuật. Bí quyết là tạo một bản sao từ 'this'. Ví dụ: 'A ret = * this; ret * = rhs; return ret; ' – Paranaix

Trả lời

13

Giống như Lucian đã nói, bạn không thể liên kết đối tượng tạm thời với tham chiếu không phải const. Sự mong đợi của trình biên dịch là đối tượng sẽ ngừng tồn tại sau biểu thức để nó không có ý nghĩa để sửa đổi nó.

Để khắc phục mã của bạn, loại bỏ tạm thời (làm đối số const& làm cho không có ý nghĩa trong operator *=):

A operator*(A a, const A& b) 
{ 
    return a *= b; 
} 
+0

@Ben Tôi cần cà phê ... Để bảo vệ danh dự của tôi, điều này (vượt qua giá trị) là cách tôi thường viết nó khi tôi thức dậy. –

+0

Đơn giản hơn nhiều. Và được tối ưu hóa hơn, vì nó có thể di chuyển khi thông số thực tế là giá trị x. –

5

Khi bạn viết A(a), bạn tạo một tạm thời loại A (một rvalue) mà bạn sao chép -construct với a. C++ nói rằng không có giá trị rvalue nào có thể được chuyển thành tham chiếu không const. Visual Studio là một chút cẩu thả về quy tắc này, nhưng gcc và tương tự thi hành nó.

Để khắc phục, hãy thử điều này (giống hệt nhau, nhưng bạn tạo một giá trị bằng cách đặt tên biến đó). Thông tin thêm về giá trị l và r here

A operator*(A a, const A& b) 
{ 
    return a *= b; 
} 
+2

Phản đối tương tự như tôi đã đăng trên câu trả lời của Konrad. –

+0

Cả hai đều chính xác. Nhưng đôi khi, bạn không cần tạo bản sao của một thao tác *. ví dụ. Toán tử Vector * sẽ không sử dụng * = để biểu thị * – crazyjul

+0

"Visual Studio hơi cẩu thả về quy tắc này ...": Visual Studio bắt được điều này nếu bạn đang chạy ở mức cảnh báo 4/xử lý cảnh báo dưới dạng lỗi (như là khôn ngoan) . – mwigdahl

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