2015-10-11 4 views
0

Я хотел бы определить оператора ostream, чтобы позволить мне легко выводить переменные типа alglib::complex. Чтобы предоставить рабочий пример без включения библиотеки alglib, я вместо этого перегружу вывод complex<double> (это пояснение из-за более ранней версии вопроса). В заголовочном файле «my_class.h» Я имеюФункция друга, определяющая оператор ostream

using namespace std; 
#include <complex> 
#include <iostream> 

class my_class { 

    public: 

    ostream& operator << (std::ostream& os, complex<double> a) { 
     os << "(" << real(a) << "," << imag(a) << ")"; 
     return os; 
    } 

    void output(complex<double>); 

    my_class() {} 
    ~my_class() {} 
}; 

И в исходном файле «my_class.cpp» У меня есть

#include "my_class.h" 

void my_class::output(complex<double> cd) { 
    cout << cd << endl; 
} 

Наконец у меня есть основной файл метод «run_my_class.cpp»:

#include "my_class.h" 

int main(int argc, const char* argv[]) { 

    my_class obj; 
    complex<double> cd=complex<double>(1.0,-1.0); 
    obj.output(cd); 

} 

Я пытаюсь скомпилировать с помощью

g++ -c my_class.cpp 

, но это дает мне ошибку

my_class.h:9:62: error: ‘std::ostream& my_class::operator<<(std::ostream&, std::complex<double>)’ must take exactly one argument 
ostream& operator << (std::ostream& os, complex<double> a) { 

Однако, если определить оператор как друг, а именно friend ostream& operator << (std::ostream& os, complex<double> a), он собирает и компилировать основной метод:

g++ run_my_class.cpp my_class.o -o run_my_class 

И это работает, как должны , Однако это не то, на что похоже ключевое слово friend. Есть ли лучший способ сделать эту работу?

+1

Почему вы делаете оператор вывода другом класса 'my_class'? Вы даже не используете 'my_class' в функциях? –

+2

Ошибка почти звучит так, как будто для аргументов не найден жизнеспособный 'operator <<', и вместо этого использовался оператор free rvalue-ref forwarder '(basic_ostream <..> &&, T const &)'. Предоставьте [MCVE] (http://stackoverflow.com/help/MCVE) соответствующий контекст. – dyp

+0

@JoachimPileborg Чтобы класс мог использовать оператор ostream. Я не мог заставить его сработать без «друга». Но может быть, есть лучший способ? – jorgen

ответ

4

Поскольку operator << будет называться на std::ostream, вы не можете определить эту процедуру в качестве функции члена для my_class, вы должны определить его в качестве глобальной функции, так как это операция для std::ostream, не my_class.

Поставив friend ключевое слово в объявлении, вы говорите, что вы хотите, чтобы объявить operator << как друг глобальной функции (не член функция!). В стандарте C++ вы можете указать определение функции friend, но оно не будет функцией-членом. Это же, как и в следующем, более ясно:

#include <complex> 
#include <iostream> 

class my_class { 

public: 

    friend ostream& operator << (std::ostream& os, complex<double> a); 

    void output(complex<double>); 

    my_class() {} 
    ~my_class() {} 
}; 

std::ostream& operator << (std::ostream& os, complex<double> a) { 
    os << "(" << real(a) << "," << imag(a) << ")"; 
    return os; 
} 

Как уже отмечались в комментариях, использование friend не нужно здесь.

Не относится к вопросу, но имейте в виду, что разрешение пространств имен в заголовочном файле, как правило, действительно очень плохой идеей, поскольку все остальные файлы, включая это, будут также неявно разрешать это пространство имен. Это может легко привести к неприятным ошибкам компиляции в долгосрочной перспективе.

+0

Ваше использование выражений «метод» и «функция» не соответствует официальной терминологии C++. Правильными могут быть «функция-член» и «глобальная функция». Это особенно вводит в заблуждение и вводит в заблуждение использование слова «функция», как если бы оно не было (также) относится к функциям-членам. «Метод» - это * неофициально используемый синоним для функций-членов. –

+0

@ChristianHackl Спасибо за комментарий, я пересмотрел свой ответ. Хотя я до сих пор считаю, что разница между методом и функцией не должна смущать никого, это общие условия ООП, не связанные с конкретным языком. Тем не менее, это вопрос на C++, поэтому у вас есть своя точка. – mcserep

1

Я бы не назвал это лучшим способом, но более понятным способом.

Вот ваш оператор поток снова:

ostream& operator << (std::ostream& os, complex<double> a) { 
     os << "(" << real(a) << "," << imag(a) << ")"; 
     return os; 
} 

Его первый параметром является выходным потоком. Поскольку у вас нет доступа к выходному потоку, вы не можете использовать оператор потока вывода в качестве функции-члена, если только вы не сделаете его другом класса.

Если вы хотите избежать использования друга, вы всегда можете определить его как функцию, внешнюю по отношению к классу, и это наиболее распространенный способ.

Смежные вопросы