2012-05-24 2 views
64

ахоператор << должны точно один аргумент

#include "logic.h" 
... 

class A 
{ 
friend ostream& operator<<(ostream&, A&); 
... 
}; 

logic.cpp

#include "a.h" 
... 
ostream& logic::operator<<(ostream& os, A& a) 
{ 
... 
} 
... 

Когда я компиляции, он говорит:

станд :: ostream & логика :: оператор < < (std :: ostream &, A &) 'должен принимать ровно один аргумент.

В чем проблема?

ответ

90

Проблема заключается в том, что вы определяете его внутри класса, который

а) означает, что второй аргумент неявно (this) и

б) он не будет делать то, что вы хотите это сделать, а именно продлить std::ostream.

Вы должны определить его в качестве свободной функции:

class A { /* ... */ }; 
std::ostream& operator<<(std::ostream&, const A& a); 
+7

Кроме того, он объявляет его как функцию друга и определяет его как я mber. – asaelr

40

Функция друга не функция, так что проблема в том, что вы объявляете operator<< как друга A:

friend ostream& operator<<(ostream&, A&); 

, то попробуйте определить его как функцию-член класса logic

ostream& logic::operator<<(ostream& os, A& a) 
      ^^^^^^^ 

Вы смущены тем, является ли logic классом или пространством имен?

Ошибка в том, что вы пытались определить член operator<<, принимая два аргумента, что означает, что он принимает три аргумента, включая неявный параметр this. Оператор может принимать только два аргумента, так что, когда вы пишете a << b, два аргумента: a и b.

Вы хотите определить ostream& operator<<(ostream&, const A&) как функция -Члена не, безусловно, не в качестве члена logic, так как он не имеет ничего общего с этим классом!

std::ostream& operator<<(std::ostream& os, const A& a) 
{ 
    return os << a.number; 
} 
0

Я столкнулся с этой проблемой с шаблонами. Вот более общее решение, которое я должен был использовать:

template class <T> 
class myClass 
{ 
    int myField; 

    // Helper function accessing my fields 
    void toString(std::ostream&) const; 

    // Friend means operator<< can use private variables 
    // It needs to be declared as a template, but T is taken 
    template <class U> 
    friend std::ostream& operator<<(std::ostream&, const myClass<U> &); 
} 

// Operator is a non-member and global, so it's not myClass<U>::operator<<() 
// Because of how C++ implements templates the function must be 
// fully declared in the header for the linker to resolve it :(
template <class U> 
std::ostream& operator<<(std::ostream& os, const myClass<U> & obj) 
{ 
    obj.toString(os); 
    return os; 
} 

Сейчас: функция * Мой ToString() не может быть рядный, если он будет спрятан в CPP. * Вы застряли с некоторым кодом в заголовке, я не мог избавиться от него. * Оператор вызовет метод toString(), он не является встроенным.

Тело оператора < < может быть объявлено в статье friend или вне класса. Оба варианта уродливы.:(

Может быть, я недоразумение или что-то отсутствует, но только вперед объявить шаблон оператор не связывает в НКУ

Это тоже работает:.

template class <T> 
class myClass 
{ 
    int myField; 

    // Helper function accessing my fields 
    void toString(std::ostream&) const; 

    // For some reason this requires using T, and not U as above 
    friend std::ostream& operator<<(std::ostream&, const myClass<T> &) 
    { 
     obj.toString(os); 
     return os; 
    } 
} 

Я думаю, вы также можете избегайте проблем с шаблонами, вызывающих объявления в заголовках, если вы используете родительский класс, который не является шаблоном для реализации оператора < <, и используйте метод virtual toString().