Nếu bạn định nghĩa operator<<
là một hàm thành viên, nó sẽ có cú pháp phân tách khác với khi bạn sử dụng một hàm không phải thành viên operator<<
. Một không phải thành viên operator<<
là một toán tử nhị phân, trong đó một thành viên operator<<
là một toán tử một ngôi.
// Declarations
struct MyObj;
std::ostream& operator<<(std::ostream& os, const MyObj& myObj);
struct MyObj
{
// This is a member unary-operator, hence one argument
MyObj& operator<<(std::ostream& os) { os << *this; return *this; }
int value = 8;
};
// This is a non-member binary-operator, 2 arguments
std::ostream& operator<<(std::ostream& os, const MyObj& myObj)
{
return os << myObj.value;
}
Vậy .... bạn thực sự gọi họ như thế nào? Các toán tử theo một số cách khác thường, tôi sẽ thách thức bạn viết operator<<(...)
cú pháp trong đầu để làm cho mọi thứ có ý nghĩa.
MyObj mo;
// Calling the unary operator
mo << std::cout;
// which decomposes to...
mo.operator<<(std::cout);
Hoặc bạn có thể cố gắng gọi toán tử nhị phân không phải thành viên:
MyObj mo;
// Calling the binary operator
std::cout << mo;
// which decomposes to...
operator<<(std::cout, mo);
Bạn không có nghĩa vụ phải làm cho các toán tử này hoạt động một cách trực quan khi bạn biến chúng thành các hàm thành viên, bạn có thể xác định operator<<(int)
dịch chuyển sang trái một số biến thành viên nếu bạn muốn, hiểu rằng mọi người có thể hơi mất cảnh giác, bất kể bạn có bao nhiêu nhận xét viết.
Gần như cuối cùng, có thể đôi khi cả hai phân tách cho một cuộc gọi tổng đài đều hợp lệ, bạn có thể gặp rắc rối ở đây và chúng tôi sẽ hoãn cuộc trò chuyện đó.
Cuối cùng, hãy lưu ý rằng nó có thể kỳ lạ như thế nào khi viết một toán tử thành viên một ngôi được cho là trông giống như một toán tử nhị phân (vì bạn có thể làm cho các toán tử thành viên ảo ..... cũng cố gắng không phát triển và chạy theo con đường này .... )
struct MyObj
{
// Note that we now return the ostream
std::ostream& operator<<(std::ostream& os) { os << *this; return os; }
int value = 8;
};
Cú pháp này sẽ gây khó chịu cho nhiều lập trình viên bây giờ ....
MyObj mo;
mo << std::cout << "Words words words";
// this decomposes to...
mo.operator<<(std::cout) << "Words words words";
// ... or even further ...
operator<<(mo.operator<<(std::cout), "Words words words");
Lưu ý cách cout
đối số thứ hai trong chuỗi ở đây .... kỳ quặc phải không?