Piszę małą bibliotekę macierzy w C ++ do operacji na macierzach. Jednak mój kompilator narzeka, a wcześniej tego nie robił. Ten kod pozostawiono na półce przez 6 miesięcy, aw międzyczasie uaktualniłem komputer z debian etch do lenny (g ++ (Debian 4.3.2-1.1) 4.3.2), jednak mam ten sam problem w systemie Ubuntu z tym samym g ++ .
Oto odpowiednia część mojej klasy macierzowej:
namespace Math
{
class Matrix
{
public:
[...]
friend std::ostream& operator<< (std::ostream& stream, const Matrix& matrix);
}
}
I „wdrożenie”:
using namespace Math;
std::ostream& Matrix::operator <<(std::ostream& stream, const Matrix& matrix) {
[...]
}
Oto błąd podany przez kompilator:
matrix.cpp: 459: error: 'std :: ostream & Math :: Matrix :: operator << (std :: ostream &, const Math :: Matrix &)' musi wziąć dokładnie jeden argument
Jestem trochę zdezorientowany tym błędem, ale z drugiej strony mój C ++ trochę się zardzewiał po tym, jak dużo Java napisałem przez te 6 miesięcy. :-)
źródło
operator<<
muszą być w przestrzeni nazwMath
? Wydaje się, że powinien on znajdować się w globalnej przestrzeni nazw. Zgadzam się, że mój kompilator chce, aby był w przestrzeni nazwMath
, ale to nie ma dla mnie sensu.Mówię tylko o jednej innej możliwości: lubię do tego używać definicji znajomych:
Funkcja zostanie automatycznie skierowana do otaczającej przestrzeni nazw
Math
(nawet jeśli jej definicja pojawia się w zakresie tej klasy), ale nie będzie widoczna, dopóki nie wywołasz operatora << za pomocą obiektu Matrix, który sprawi, że wyszukiwanie zależne od argumentów znajdzie tę definicję operatora. Może to czasem pomóc w niejednoznacznych wywołaniach, ponieważ jest niewidoczne dla typów argumentów innych niż Matrix. Pisząc jego definicję, możesz również odwoływać się bezpośrednio do nazw zdefiniowanych w Matrycy i do samej Matrycy, bez kwalifikowania nazwy jakimś długim prefiksem i podawania parametrów szablonu, takich jakMath::Matrix<TypeA, N>
.źródło
Aby dodać do odpowiedzi Mehrdad,
W twojej realizacji
źródło
Zakładając, że mówimy o przeciążeniu
operator <<
dla wszystkich klas pochodnych odstd::ostream
obsłużyćMatrix
klasy (a nie przeciążenia<<
dlaMatrix
klasy), sensowniejsze jest zadeklarowanie funkcji przeciążenia poza przestrzenią nazw Math w nagłówku.Użyj funkcji przyjaciela tylko wtedy, gdy nie można uzyskać tej funkcji za pomocą publicznych interfejsów.
Matrix.h
Pamiętaj, że przeciążenie operatora jest zadeklarowane poza przestrzenią nazw.
Matrix.cpp
Z drugiej strony, jeśli funkcja przeciążenia robi muszą być wykonane znajomego tj potrzebuje dostępu do członków prywatnych i chronionych.
Math.h
Musisz zawrzeć definicję funkcji w bloku przestrzeni nazw zamiast po prostu
using namespace Math;
.Matrix.cpp
źródło
W C ++ 14 możesz użyć następującego szablonu do wydrukowania dowolnego obiektu, który ma const T :: print (std :: ostream &); członek.
W C ++ 20 można używać pojęć.
źródło
std::ostream&
, skoro i tak jest to typ zwrotu?