
Mathias van der Vlies
Ich schreibe eine kleine Matrixbibliothek in C++ für Matrixoperationen. Allerdings beschwert sich mein Compiler, wo vorher nicht. Dieser Code wurde 6 Monate lang in einem Regal gelassen und zwischendurch habe ich meinen Computer von Debian Etch auf Lenny (g++ (Debian 4.3.2-1.1) 4.3.2 ) aktualisiert, aber ich habe das gleiche Problem auf einem Ubuntu-System mit demselben g++ .
Hier ist der relevante Teil meiner Matrixklasse:
namespace Math
{
class Matrix
{
public:
[...]
friend std::ostream& operator<< (std::ostream& stream, const Matrix& matrix);
}
}
Und die “Umsetzung”:
using namespace Math;
std::ostream& Matrix::operator <<(std::ostream& stream, const Matrix& matrix) {
[...]
}
Dies ist der vom Compiler ausgegebene Fehler:
matrix.cpp:459: Fehler: ‘std::ostream& Math::Matrix::operator<<(std::ostream&, const Math::Matrix&)' muss genau ein Argument haben
Ich bin ein bisschen verwirrt von diesem Fehler, aber andererseits ist mein C++ etwas eingerostet, nachdem ich in diesen 6 Monaten viel Java gemacht habe. 🙂
Nur um Ihnen von einer anderen Möglichkeit zu erzählen: Ich verwende dafür gerne Freundschaftsdefinitionen:
namespace Math
{
class Matrix
{
public:
[...]
friend std::ostream& operator<< (std::ostream& stream, const Matrix& matrix) {
[...]
}
};
}
Die Funktion wird automatisch auf den umgebenden Namespace ausgerichtet Math
(obwohl seine Definition innerhalb des Geltungsbereichs dieser Klasse erscheint), aber nicht sichtbar ist, es sei denn, Sie rufen operator<< mit einem Matrix-Objekt auf, wodurch eine argumentabhängige Suche diese Operatordefinition findet. Das kann manchmal bei mehrdeutigen Aufrufen hilfreich sein, da es für andere Argumenttypen als Matrix unsichtbar ist. Beim Schreiben seiner Definition können Sie auch direkt auf in Matrix definierte Namen und auf Matrix selbst verweisen, ohne den Namen mit einem möglicherweise langen Präfix zu qualifizieren und Vorlagenparameter wie bereitzustellen Math::Matrix<TypeA, N>
.
Sie haben Ihre Funktion als deklariert friend
. Es ist kein Mitglied der Klasse. Sie sollten entfernen Matrix::
von der Umsetzung. friend
bedeutet, dass die angegebene Funktion (die kein Mitglied der Klasse ist) auf private Mitgliedsvariablen zugreifen kann. Die Art und Weise, wie Sie die Funktion implementiert haben, ist wie eine Instanzmethode für Matrix
Klasse, was falsch ist.

Kal
Um die Mehrdad-Antwort zu ergänzen,
namespace Math
{
class Matrix
{
public:
[...]
}
std::ostream& operator<< (std::ostream& stream, const Math::Matrix& matrix);
}
In Ihrer Umsetzung
std::ostream& operator<<(std::ostream& stream,
const Math::Matrix& matrix) {
matrix.print(stream); //assuming you define print for matrix
return stream;
}

sanjivr
Angenommen, wir sprechen von Überlastung operator <<
für alle abgeleiteten Klassen std::ostream
um die zu handhaben Matrix
Klasse (und nicht überladen <<
zum Matrix
Klasse), ist es sinnvoller, die Überladungsfunktion außerhalb des Math-Namespace im Header zu deklarieren.
Verwenden Sie eine Friend-Funktion nur, wenn die Funktionalität nicht über die öffentlichen Schnittstellen erreicht werden kann.
Matrix.h
namespace Math {
class Matrix {
//...
};
}
std::ostream& operator<<(std::ostream&, const Math::Matrix&);
Beachten Sie, dass die Operatorüberladung außerhalb des Namespace deklariert wird.
Matrix.cpp
using namespace Math;
using namespace std;
ostream& operator<< (ostream& os, const Matrix& obj) {
os << obj.getXYZ() << obj.getABC() << '\n';
return os;
}
Andererseits, wenn Ihre Überlastfunktion tut muss zum Freund gemacht werden, dh braucht Zugriff auf private und geschützte Mitglieder.
Math.h
namespace Math {
class Matrix {
public:
friend std::ostream& operator<<(std::ostream&, const Matrix&);
};
}
Sie müssen die Funktionsdefinition mit einem Namensraumblock einschließen, anstatt nur using namespace Math;
.
Matrix.cpp
using namespace Math;
using namespace std;
namespace Math {
ostream& operator<<(ostream& os, const Matrix& obj) {
os << obj.XYZ << obj.ABC << '\n';
return os;
}
}

QuentinUK
In C++14 können Sie die folgende Vorlage verwenden, um jedes Objekt zu drucken, das eine T::print(std::ostream&)const; Mitglied.
template<class T>
auto operator<<(std::ostream& os, T const & t) -> decltype(t.print(os), os)
{
t.print(os);
return os;
}
In C++20 können Konzepte verwendet werden.
template<typename T>
concept Printable = requires(std::ostream& os, T const & t) {
{ t.print(os) };
};
template<Printable T>
std::ostream& operator<<(std::ostream& os, const T& t) {
t.print(os);
return os;
}
Ich möchte dies mit einem überladenden Beispiel ein wenig vereinfachen <<
um ein Array zu drucken.
- Führen Sie zuerst beide Objekttypen um die herum
<<
Operator
- Erstellen Sie eine Funktion zum Überladen des Operators wie folgt.
#include<iostream>
using namespace std;
void operator<<(ostream& os, int arr[]) {
for (int i = 0;i < 10;i++) {
cout << arr[i] << " ";
}
cout << endl;
}
int main() {
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
cout << arr;
}
Wenn auch eine Kaskadierung von Operatoren erforderlich ist, stellen Sie sicher, dass Sie zurückkehren cout
Objekt in der überladenen Funktion wie folgt,
#include<iostream>
using namespace std;
ostream& operator<<(ostream& os, int arr[]) {
for (int i = 0;i < 10;i++) {
cout << arr[i] << " ";
}
cout << endl;
return os;
}
int main() {
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 11,22,33,44,55,66,77,88,99,100 };
// cascading of operators
cout << arr << arr2;
}
9945800cookie-checkWie kann man denyes