Jak prawidłowo przeciążyć operator

Piszę małą bibliotekę macierzową w C++ do operacji macierzowych. Jednak mój kompilator narzeka, gdzie wcześniej nie. Ten kod został pozostawiony na półce przez 6 miesięcy, a pomiędzy nimi zaktualizowałem mój komputer z debian etch do lenny (G++ (Debian 4.3.2-1.1) 4.3.2 ) jednak mam ten sam problem na systemie Ubuntu z tym samym g++.

Oto odpowiednia część mojej klasy matrix:

namespace Math
{
    class Matrix
    {
    public:

        [...]

        friend std::ostream& operator<< (std::ostream& stream, const Matrix& matrix);
    }
}

I "realizacja":

using namespace Math;

std::ostream& Matrix::operator <<(std::ostream& stream, const Matrix& matrix) {

    [...]

}

Jest to błąd podany przez kompilator:

Matrix.cpp: 459: error: 'std:: ostream& Math:: Matrix:: operator

Jestem trochę zdezorientowany tym błędem, ale znowu mój C++ trochę zardzewiał po zrobieniu wielu Javy przez te 6 miesięcy. :-)

Author: Agnel Kurian, 2009-01-24

5 answers

Zadeklarowałeś swoją funkcję jako friend. Nie należy do klasy. Należy usunąć Matrix:: z implementacji. friend oznacza, że określona funkcja (która nie jest członkiem klasy) może uzyskać dostęp do prywatnych zmiennych członkowskich. Sposób w jaki zaimplementowałeś tę funkcję jest jak metoda instancji dla klasy Matrix, która jest błędna.

 107
Author: Mehrdad Afshari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-24 16:37:35

Mówię ci o jeszcze jednej możliwości: lubię używać do tego definicji przyjaciół:

namespace Math
{
    class Matrix
    {
    public:

        [...]

        friend std::ostream& operator<< (std::ostream& stream, const Matrix& matrix) {
            [...]
        }
    };
}

Funkcja będzie automatycznie kierowana do otaczającej przestrzeni nazw Math (nawet jeśli jej definicja pojawia się w zakresie tej klasy), ale nie będzie widoczna, chyba że wywołasz operatorMath::Matrix<TypeA, N>.

 126
Author: Johannes Schaub - litb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-24 22:28:38

Aby dodać do Mehrdad odpowiedź,

namespace Math
{
    class Matrix
    {
       public:

       [...]


    }   
    std::ostream& operator<< (std::ostream& stream, const Math::Matrix& matrix);
}

W Twojej implementacji

std::ostream& operator<<(std::ostream& stream, 
                     const Math::Matrix& matrix) {
    matrix.print(stream); //assuming you define print for matrix 
    return stream;
 }
 65
Author: kal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-24 19:00:05

Zakładając, że mówimy o przeciążeniu operator << dla wszystkich klas wywodzących się z std::ostream do obsługi klasy Matrix (i nie przeciążeniu << dla klasy Matrix), bardziej sensowne jest zadeklarowanie funkcji przeciążenia poza przestrzenią nazw w nagłówku.

Użyj funkcji friend tylko wtedy, gdy nie można jej osiągnąć za pomocą publicznych interfejsów.

Matrix.h

namespace Math { 
    class Matrix { 
        //...
    };  
}
std::ostream& operator<<(std::ostream&, const Math::Matrix&);

Zauważ, że przeciążenie operatora jest deklarowane poza przestrzeń nazw.

Matrix.cpp

using namespace Math;
using namespace std;

ostream& operator<< (ostream& os, const Matrix& obj) {
    os << obj.getXYZ() << obj.getABC() << '\n';
    return os;
}

Z drugiej strony, jeśli twoja funkcja przeciążenia robi musi zostać zaprzyjaźniona, tzn. potrzebuje dostępu do prywatnych i chronionych członków.

Matematyka.h

namespace Math {
    class Matrix {
        public:
            friend std::ostream& operator<<(std::ostream&, const Matrix&);
    };
}

Musisz załączyć definicję funkcji blokiem przestrzeni nazw zamiast 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;
    }                 
}
 55
Author: sanjivr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-15 14:10:27

W C++14 możesz użyć następującego szablonu, aby wydrukować dowolny obiekt, który ma element t::print (std::ostream&)const;.

template<class T>
auto operator<<(std::ostream& os, const T& t) -> decltype(t.print(os), os) 
{ 
    t.print(os); 
    return os; 
} 
 25
Author: QuentinUK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-05 08:24:36