Wenn Sie operator<<
als Elementfunktion definieren, hat diese eine andere zerlegte Syntax als wenn Sie ein Nichtmitglied verwendet haben operator<<
. Ein Nichtmitglied operator<<
ist ein binärer Operator, wobei ein Mitglied operator<<
ein unärer Operator ist.
// 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;
}
Also ... wie nennt man sie wirklich? Operatoren sind in gewisser Hinsicht seltsam. Ich fordere Sie auf, die operator<<(...)
Syntax in Ihren Kopf zu schreiben , damit die Dinge Sinn ergeben.
MyObj mo;
// Calling the unary operator
mo << std::cout;
// which decomposes to...
mo.operator<<(std::cout);
Oder Sie könnten versuchen, den Nicht-Mitglied-Binäroperator aufzurufen:
MyObj mo;
// Calling the binary operator
std::cout << mo;
// which decomposes to...
operator<<(std::cout, mo);
Sie sind nicht verpflichtet, diese Operatoren dazu zu bringen, sich intuitiv zu verhalten, wenn Sie sie zu Elementfunktionen machen. Sie können festlegen, dass eine Elementvariable operator<<(int)
nach links verschoben wird, wenn Sie möchten schreiben.
Fast schließlich kann es Zeiten geben, in denen beide Zerlegungen für einen Operatoranruf gültig sind. Hier können Probleme auftreten, und wir werden dieses Gespräch verschieben.
Beachten Sie zum Schluss, wie seltsam es sein kann, einen unären Member-Operator zu schreiben, der wie ein binärer Operator aussehen soll (da Sie Member-Operatoren virtuell machen können ..... auch versuchen, diesen Pfad nicht weiterzuentwickeln und zu durchlaufen .... )
struct MyObj
{
// Note that we now return the ostream
std::ostream& operator<<(std::ostream& os) { os << *this; return os; }
int value = 8;
};
Diese Syntax wird jetzt viele Programmierer irritieren ...
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");
Beachten Sie, wie das cout
zweite Argument in der Kette hier ist .... ungerade richtig?