Domanda

Sto scrivendo una piccola libreria di matrici in C ++ per operazioni con matrici. Tuttavia il mio compilatore si lamenta, mentre prima non lo faceva. Questo codice è stato lasciato su uno scaffale per 6 mesi e nel frattempo ho aggiornato il mio computer da debian etch a lenny (g ++ (Debian 4.3.2-1.1) 4.3.2 ) tuttavia ho lo stesso problema su un sistema Ubuntu con lo stesso g ++.

Ecco la parte rilevante della mia classe di matrici:

namespace Math
{
    class Matrix
    {
    public:

        [...]

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

E la " implementazione " ;:

using namespace Math;

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

    [...]

}

Questo è l'errore dato dal compilatore:

  

matrix.cpp: 459: errore: 'std :: ostream & amp;   Math :: Matrix :: operator < < (std :: ostream & amp ;,   const Math :: Matrix & amp;) 'deve prendere   esattamente un argomento

Sono un po 'confuso da questo errore, ma poi il mio C ++ è diventato un po' arrugginito dopo aver fatto molta Java in quei 6 mesi. : -)

È stato utile?

Soluzione

Hai dichiarato la tua funzione di amico . Non è un membro della classe. È necessario rimuovere Matrix :: dall'implementazione. friend significa che la funzione specificata (che non è un membro della classe) può accedere alle variabili dei membri privati. Il modo in cui hai implementato la funzione è come un metodo di istanza per la classe Matrix che è sbagliato.

Altri suggerimenti

Ti sto solo raccontando un'altra possibilità: mi piace usare definizioni di amici per questo:

namespace Math
{
    class Matrix
    {
    public:

        [...]

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

La funzione verrà automaticamente indirizzata nello spazio dei nomi circostante Math (anche se la sua definizione appare nell'ambito di quella classe) ma non sarà visibile se non chiami l'operatore < < con un oggetto Matrix che renderà la ricerca dipendente dall'argomento trovare quella definizione dell'operatore. Questo a volte può aiutare con chiamate ambigue, poiché è invisibile per tipi di argomento diversi da Matrix. Quando scrivi la sua definizione, puoi anche fare riferimento direttamente ai nomi definiti in Matrix e alla stessa Matrix, senza qualificare il nome con un prefisso eventualmente lungo e fornendo parametri del modello come Math :: Matrix < TypeA, N > .

Per aggiungere alla risposta Mehrdad,

namespace Math
{
    class Matrix
    {
       public:

       [...]


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

Nella tua implementazione

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

Supponendo che stiamo parlando di sovraccaricare l'operatore < < per tutte le classi derivate da std :: ostream per gestire il Matrix classe (e non sovraccaricando < < per la classe Matrix ), ha più senso dichiarare la funzione di sovraccarico al di fuori dello spazio dei nomi Math nell'intestazione.

Utilizzare una funzione amico solo se la funzionalità non può essere raggiunta tramite le interfacce pubbliche.

Matrix.h

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

Notare che il sovraccarico dell'operatore è dichiarato fuori dallo spazio dei nomi.

Matrix.cpp

using namespace Math;
using namespace std;

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

D'altra parte, se la tua funzione di sovraccarico ha deve essere resa amica, cioè ha bisogno di accedere a membri privati ??e protetti.

Math.h

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

È necessario racchiudere la definizione della funzione con un blocco dello spazio dei nomi anziché solo utilizzando lo spazio dei nomi 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;
    }                 
}

In C ++ 14 puoi usare il seguente modello per stampare qualsiasi oggetto che ha una const T :: print (std :: ostream & amp;); membro.

template<class T>
auto operator<<(std::ostream& os, const T& t) -> decltype(t.print(os), os) 
{ 
    t.print(os); 
    return os; 
} 
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top