Вопрос

Я пишу небольшую матричную библиотеку на C ++ для матричных операций.Однако мой компилятор жалуется, там, где раньше этого не было.Этот код пролежал на полке 6 месяцев, и в промежутке я обновил свой компьютер с debian etch на lenny (g ++ (Debian 4.3.2-1.1) 4.3.2 ) однако у меня такая же проблема в системе Ubuntu с тем же g ++.

Вот соответствующая часть моего класса matrix:

namespace Math
{
    class Matrix
    {
    public:

        [...]

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

И "реализация":

using namespace Math;

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

    [...]

}

Это ошибка, выдаваемая компилятором:

матрица.cpp:459:ошибка:'std::ostream& Математика::Матрица::оператор<<(std::ostream&, const Math::Matrix&)' должен принимать ровно один аргумент

Я немного смущен этой ошибкой, но опять же, мой C ++ немного подзабылся после того, как я много работал на Java в течение этих 6 месяцев.:-)

Это было полезно?

Решение

Вы объявили свою функцию как friend.Это не член класса.Вы должны удалить Matrix:: из реализации. friend означает, что указанная функция (которая не является членом класса) может обращаться к закрытым переменным-членам.То, как вы реализовали функцию, похоже на метод экземпляра для Matrix класс, который является неправильным.

Другие советы

Просто рассказываю вам об одной другой возможности:Мне нравится использовать определения друзей для этого:

namespace Math
{
    class Matrix
    {
    public:

        [...]

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

Функция будет автоматически нацелена на окружающее пространство имен Math (даже если его определение отображается в пределах этого класса), но не будет видно, если вы не вызовете operator<< с помощью матричного объекта, который сделает поиск зависимым от аргумента, найдите это определение оператора.Иногда это может помочь при неоднозначных вызовах, поскольку оно невидимо для типов аргументов, отличных от Matrix.При написании его определения вы также можете ссылаться непосредственно на имена, определенные в Matrix, и на саму Matrix, не уточняя имя каким-либо возможно длинным префиксом и не предоставляя параметры шаблона, такие как Math::Matrix<TypeA, N>.

Чтобы добавить к ответу Мехрдада ,

namespace Math
{
    class Matrix
    {
       public:

       [...]


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

В вашей реализации

std::ostream& operator<<(std::ostream& stream, 
                     const Math::Matrix& matrix) {
    matrix.print(stream); //assuming you define print for matrix 
    return stream;
 }

Предполагая, что мы говорим о перегрузке operator << для всех классов , производных от std::ostream чтобы справиться с Matrix класс (и не перегружающий << для Matrix class), имеет смысл объявить функцию перегрузки вне пространства имен Math в заголовке.

Используйте дружественную функцию только в том случае, если функциональность не может быть достигнута через общедоступные интерфейсы.

Матрица.h

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

Обратите внимание, что перегрузка оператора объявлена вне пространства имен.

Matrix.cpp

using namespace Math;
using namespace std;

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

С другой стороны, если ваша функция перегрузки делает нужно, чтобы у тебя появился друг, т.е.необходим доступ к частным и защищенным пользователям.

Математика.h

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

Вам нужно заключить определение функции в блок пространства имен, а не просто 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;
    }                 
}

В C ++ 14 вы можете использовать следующий шаблон для печати любого объекта, который имеет 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; 
} 
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top