ах
#include "logic.h"
...
class A
{
friend ostream& operator<<(ostream&, A&);
...
};
logic.cpp
#include "a.h"
...
ostream& logic::operator<<(ostream& os, A& a)
{
...
}
...
Когда я компилирую, он говорит:
std :: ostream & logic :: operator << (std :: ostream &, A &) 'должен принимать ровно один аргумент.
В чем проблема?
c++
operator-overloading
iostream
Как Как
источник
источник
Функция друга не является функцией-членом, поэтому проблема в том, что вы объявляете
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; }
источник
Я столкнулся с этой проблемой с шаблонными классами. Вот более общее решение, которое мне пришлось использовать:
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 (), он не встроен.
Тело оператора << может быть объявлено в предложении друга или вне класса. Оба варианта уродливы. :(
Возможно, я что-то не понимаю или что-то упускаю, но простое прямое объявление шаблона оператора не ссылается на gcc.
Это тоже работает:
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; } }
Я думаю, вы также можете избежать проблем с шаблонами, вызывающих объявления в заголовках, если вы используете родительский класс, который не имеет шаблона для реализации operator <<, и используете виртуальный метод toString ().
источник
Если вы определяете
operator<<
функцию-член, она будет иметь другой разложенный синтаксис, чем если бы вы использовали не-членoperator<<
. Не-членoperator<<
- это бинарный оператор, а членoperator<<
- унарный оператор.// Declarations struct MyObj; std::ostream& operator<<(std::ostream& os, const MyObj& myObj); struct MyObj { // This is a member unary-operator, hence one argument MyObj& operator<<(std::ostream& os) { os << *this; return *this; } int value = 8; }; // This is a non-member binary-operator, 2 arguments std::ostream& operator<<(std::ostream& os, const MyObj& myObj) { return os << myObj.value; }
Итак .... как вы их на самом деле называете? Операторы в некотором роде странные, я предлагаю вам написать
operator<<(...)
синтаксис в уме, чтобы все было понятно.MyObj mo; // Calling the unary operator mo << std::cout; // which decomposes to... mo.operator<<(std::cout);
Или вы можете попытаться вызвать бинарный оператор, не являющийся членом:
MyObj mo; // Calling the binary operator std::cout << mo; // which decomposes to... operator<<(std::cout, mo);
Вы не обязаны заставлять эти операторы вести себя интуитивно, когда вы превращаете их в функции-члены, вы можете определить
operator<<(int)
сдвиг влево для некоторой переменной-члена, если хотите, понимая, что люди могут быть немного застигнуты врасплох, независимо от того, сколько комментариев вы можете написать.Почти наконец, могут быть моменты, когда оба разложения для вызова оператора действительны, у вас могут возникнуть проблемы, и мы отложим этот разговор.
Наконец, обратите внимание, как странно было бы написать унарный оператор-член, который должен выглядеть как бинарный оператор (поскольку вы можете сделать операторы-члены виртуальными ... также пытаясь не переходить и не спускаться по этому пути ... )
struct MyObj { // Note that we now return the ostream std::ostream& operator<<(std::ostream& os) { os << *this; return os; } int value = 8; };
Этот синтаксис сейчас будет раздражать многих программистов ....
MyObj mo; mo << std::cout << "Words words words"; // this decomposes to... mo.operator<<(std::cout) << "Words words words"; // ... or even further ... operator<<(mo.operator<<(std::cout), "Words words words");
Обратите внимание, что здесь
cout
второй аргумент в цепочке .... странно, правда?источник