2011-12-04 18 views
10

Chcę przeciążać operatora < < w jednym z moich zajęć. Podpis idzie tak:C++ - czy w pliku nagłówkowym należy zdefiniować funkcje znajomego?

friend std::ostream& operator<<(std::ostream& os, const Annuaire& obj) 

Kiedy próbuję zdefiniować go w .cpp plik jest napisane, że operator < < dokładnie trwa 1 argumentu, jednak kiedy zdefiniować go w .h, to skompilowany /działa w porządku.

ten sposób zdefiniować go w pliku .cpp:

std::ostream& Annuaire::operator<<(std::ostream& os, const Annuaire& obj){ // ... } 

Czy to ma coś wspólnego z przyjacielem funkcje muszą zostać zdefiniowane w plikach nagłówkowych?

+0

Musisz dostać '' istream' ostream' i prawo ... –

+0

Tak, twój przyjaciel jest istream i jeden w KPP jest ostream, jeżeli jest to celowe trzeba będzie 2 deklaracji przyjaciół i 2 Definicje , jeśli nie, napraw jeden lub drugi w zależności od tego, czy chcesz wejść, czy wyjść na zewnątrz. –

+0

Dzięki, to był i tak błąd kopiowania i wklejania. – Pacane

Odpowiedz

9

To może być zdefiniowane w pliku cpp, ale to musi być przynajmniej oświadczył w pliku nagłówka, w przeciwnym razie wszystkie miejsca, gdzie chcesz go używać tylko zobacz rzeczy, które daje ci strumień, a nie twoje przeciążenie.

// .h and in class 
friend std::ostream& operator<<(std::ostream& os, MyClass const& v); 

// .cpp 
std::ostream& operator<<(std::ostream& os, MyClass const& v){ 
    // print it 
} 
2

Brak takich ograniczeń; prawdopodobnie piszesz to źle. Powinno być coś takiego:

class Foo 
{ 
    int n; 

    friend std::ostream & operator<<(std::ostream &, Foo const &); 
}; 

std::ostream & operator<<(std::ostream & o, Foo const & x) 
{ 
    return o << x.n; 
} 
9

Problem polega na sposobie, w jaki go definiujesz. To nie jest członek klasy , to tylko przyjaciel z klasy. Musisz usunąć prefiks Annuaire::. Tak, to zmienić:

std::ostream& Annuaire::operator<<(std::ostream& os, const Annuaire& obj){ // ... 

do tego:

std::ostream& operator<<(std::ostream& os, const Annuaire& obj){ // ... 

Przyczyną komunikatu o błędzie jest to, że Annuaire::operator<<(std::ostream& os, const Annuaire& obj) spodziewałbym trzy argumenty: wystąpienie Annuaire że nazywa się on (jak this), ai dwa dodatkowe argumenty (os i obj).

3

funkcje przyjaciel, nawet jeśli wydają się one być zadeklarowane wewnątrz klasy nie są funkcjami członkiem, ale raczej funkcje poziomu nazw (w otaczającej przestrzeni nazw). W kodzie zadeklarować funkcję przyjaciela poprawnie, ale próby zdefiniowania jej jako funkcji składowej klasy:

std::ostream& Annuaire::operator<<(std::ostream& os, const Annuaire& obj){ 

Taka definicja byłaby dla funkcji członkowskim Annuaire, zwanego operator<<, które ma dwa argumenty, która jest nieważna jako operator<< może być przeciążona na jeden z dwóch sposobów: jako funkcja wolna, przyjmująca dwa argumenty (lewa strona i prawa ręka) lub jako funkcja składowa klasy, która pojawia się w lhs wyrażenia przyjmującego argument typ rhs. W tym konkretnym przypadku, ponieważ LHS jest std::ostream i nie można go zmodyfikować, pozostaje ci tylko możliwość korzystania z bezpłatnego funkcję:

std::ostream& operator<<(std::ostream& os, const Annuaire& obj) 
+0

+1 za dodanie notatki do otaczającego obszaru nazw. Aby dodać 'using namespace X' zanim faktyczna definicja funkcji nie jest wystarczająca. – moooeeeep

2

Jak wspomniano w odpowiedzi Dawida, w tym przypadku operator nie jest funkcja członkowska, jest po prostu funkcją przyjaciela w tej samej przestrzeni nazw. To wskazało mi właściwy kierunek w rozwiązaniu bardzo podobnej kwestii.

Zamieszczam tę odpowiedź, ponieważ nie było to dla mnie oczywiste. Być może dlatego, że plik implementacyjny, w którym dodawałem operator, nie był w pełni zamknięty w przestrzeni nazw i używał zamiast tego dyrektywy using.

Nie powinno być istotne, ale używam VS2013.

//Foo.h 
namespace Bar{ 
    class Foo 
    { 
    public: 
     Foo(); 
    private: 
     int n; 
     friend std::ostream & operator<<(std::ostream &, Foo const &); 
    }; 
} 

//Foo.cpp 
using namespace Bar; //won't apply to the operator definition 
Foo::Foo(){}// doesn't require the Bar qualifier because of the using-directive 

//the operator required the Bar namespace qualifier 
std::ostream & Bar::operator<<(std::ostream & o, Foo const & x) 
{ 
    return o << x.n; 
} 
+0

Dokładnie mój problem! Nie jestem pewien, dlaczego tak się dzieje. – Flynsee