Pergunta

Eu estou escrevendo uma biblioteca matriz pequeno em C ++ para operações de matriz. No entanto o meu compilador reclama, onde antes isso não aconteceu. Este código foi deixado em uma prateleira por 6 meses e entre eu atualizei meu computador a partir de Debian Etch para lenny (g ++ (Debian 4.3.2-1.1) 4.3.2 ) No entanto eu tenho o mesmo problema em um sistema Ubuntu com o mesmo g ++.

Aqui está a parte relevante da minha classe matriz:

namespace Math
{
    class Matrix
    {
    public:

        [...]

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

E a "implementação":

using namespace Math;

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

    [...]

}

Este é o erro dada pelo compilador:

matrix.cpp: 459: erro: 'std :: ostream & Math :: Matrix :: operator << (std :: ostream &, const Math :: Matrix &)' deve tomar exatamente um argumento

Estou um pouco confuso com este erro, mas mais uma vez o meu C ++ tem obtido um enferrujado pouco depois de fazer lotes de Java esses 6 meses. : -)

Foi útil?

Solução

Você declararam sua função como friend. Não é um membro da classe. Você deve remover Matrix:: da implementação. meios friend que a função especificada (que não é um membro da classe) podem acessar variáveis ??de membro privadas. A maneira como você implementou a função é como um método de instância para a classe Matrix que é errado.

Outras dicas

Apenas avisando sobre uma outra possibilidade: Eu gosto de usar definições amigo para isso:

namespace Math
{
    class Matrix
    {
    public:

        [...]

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

A função será direcionado automaticamente para o Math namespace circundante (mesmo que sua definição aparece no âmbito dessa classe), mas não será visível a menos que você chamar operador << com um objeto Matrix que fará argumento pesquisa dependente achado que definição operador. Que às vezes podem ajudar com chamadas ambíguas, já que é invisível para outros fins que Matrix tipos de argumentos. Ao escrever a sua definição, você também pode se referir diretamente a nomes definidos em Matrix e para a própria Matrix, sem qualificar o nome com alguns possivelmente longo prefixo e fornecendo parâmetros do modelo como Math::Matrix<TypeA, N>.

Para adicionar a resposta Mehrdad,

namespace Math
{
    class Matrix
    {
       public:

       [...]


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

Na sua implementação

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

Assumindo que estamos a falar de sobrecarga operator << para todas as classes derivadas de std::ostream para lidar com a classe Matrix (e não sobrecarregar << para a classe Matrix), que faz mais sentido para declarar a função de sobrecarga fora do namespace Math no cabeçalho.

Use uma função amigo apenas se a funcionalidade não pode ser alcançado através das interfaces públicas.

Matrix.h

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

Note que a sobrecarga de operador é declarado fora do espaço de nomes.

Matrix.cpp

using namespace Math;
using namespace std;

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

Por outro lado, se a sua função de sobrecarga faz necessidade de ser feito um amigo ou seja, precisa de acesso a membros privados e protegidos.

math.h

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

Você precisa incluir a definição de função com um bloco de namespace em vez de apenas 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;
    }                 
}

Em C ++ 14 você pode usar o modelo a seguir para imprimir qualquer objeto que tem uma T :: print (std :: ostream &) const; membro.

template<class T>
auto operator<<(std::ostream& os, const T& t) -> decltype(t.print(os), os) 
{ 
    t.print(os); 
    return os; 
} 
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top