C++ - должны ли функции friend быть определены в заголовочном файле?
Я хочу перегрузить оператор
friend std::ostream& operator<<(std::ostream& os, const Annuaire& obj)
когда я пытаюсь определить его в рамках .cpp файл, он говорит, что оператор
вот как я определяю это в.файл cpp :
std::ostream& Annuaire::operator<<(std::ostream& os, const Annuaire& obj){ // ... }
имеет ли это какое-либо отношение к функциям друга, которые должны быть определены в файлах заголовков?
5 ответов
может быть определена в файле cpp, но он должен быть по крайней мере объявил в заголовочном файле, иначе все места, где вы хотите его использовать, будут видеть только то, что дает вам сам поток, а не вашу перегрузку.
// .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
}
проблема в том, как вы ее определяете. Это не класс, это просто друг класса. Вам нужно отбросить Annuaire::
префикс. Итак, измените это:
std::ostream& Annuaire::operator<<(std::ostream& os, const Annuaire& obj){ // ...
для этого:
std::ostream& operator<<(std::ostream& os, const Annuaire& obj){ // ...
причиной сообщения об ошибке является то, что Annuaire::operator<<(std::ostream& os, const Annuaire& obj)
ожидал бы три аргумента:Annuaire
экземпляр, который вызывается (как this
), и два дополнительных аргумента (os
и obj
).
функции друга, даже если они кажется для объявления внутри класса не являются функциями-членами, а скорее функциями уровня пространства имен (в заключительном пространстве имен). В вашем коде вы объявляете функцию friend правильно, но пытаетесь определить ее как функцию-член класса:
std::ostream& Annuaire::operator<<(std::ostream& os, const Annuaire& obj){
это определение будет для функции-члена Annuaire
, под названием operator<<
, что принимает два аргумента, который недействителен как operator<<
может быть перегружен одним из двух способов: как свободная функция, принимающая два аргумента (левую и правую стороны) или как функция-член класса, который появляется в lhs выражения, принимающего аргумент типа rhs. В этом конкретном случае, так как lhs std::ostream
и вы не можете изменить его, у вас остается единственная возможность использования функции:
std::ostream& operator<<(std::ostream& os, const Annuaire& obj)
Как упоминалось в ответе Дэвида, в этом случае оператор не является функцией-членом, это просто функция друга в том же пространстве имен. Это указал мне в правильном направлении в решении очень похожий вопрос.
я публикую этот ответ, потому что он не был сразу очевиден для меня. Возможно, потому, что файл реализации, в который я добавлял оператор, не был полностью заключен в пространство имен и вместо этого использовал директиву using.
не должно иметь значения, но я используя 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;
}
нет такого ограничения; вы, вероятно, просто пишете это неправильно. Должно быть что-то вроде этого:
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;
}