MyTetra Share
Делитесь знаниями!
Перегрузка еще раз
Время создания: 10.08.2017 16:28
Раздел: Computer - Programming - C++

Сигнатуры операторов ввод/вывода:


ostream& operator << (ostream& s, const Object& o)

istream& operator >> (istream& s, Object& o)


Пример из далека:


#include <iostream>

#include <sstream>

#include <iomanip>


using namespace std;


struct Duration

{

int hour;

int min;

};


Duration ReadDuration(istream& stream)

{

int h = 0;

int m = 0;

stream >> h;

stream.ignore(1); //ignore ':'

stream >> m;

return Duration{h, m};

}


void PrintDuration(ostream& stream, const Duration& dur)

{

stream << setfill('0');

stream << setw(2) << dur.hour << ':'

<< setw(2) << dur.min;

}


int main()

{

stringstream dur_ss("01:05");

Duration dur1 = ReadDuration(dur_ss);

PrintDuration(cout, dur1);

getchar();

return 0;

}


В данном коде функция ReadDuration принимает входной поток, из которого забирает часы, игнорирует разделитель двоеточия и забирает минуты. Часы и минуты заносятся в структуру Duration.

Затем, для создаем функцию PrintDuration, которая принимает выходной поток и объект типа Duration. В ней мы заполняем пропуски нулями, а ширину для каждого элемента (часы, минуты) выставляем равную двойке. И все это мы отправляем в поток.

Но постоянно вызывать функци PrintDuration не очень удобно, поэтому попробуем перегрузить оператор вывода <<, чтобы он мог на вход принимать объекты типа Duration:


#include <iostream>

#include <sstream>

#include <iomanip>


using namespace std;


struct Duration

{

int hour;

int min;

};


Duration ReadDuration(istream& stream)

{

int h = 0;

int m = 0;

stream >> h;

stream.ignore(1); //ignore ':'

stream >> m;

return Duration{h, m};

}


ostream& operator<<(ostream& stream, const Duration& dur)

{

stream << setfill('0');

stream << setw(2) << dur.hour << ':'

<< setw(2) << dur.min;

return stream;

}


int main()

{

stringstream dur_ss("01:05");

Duration dur1 = ReadDuration(dur_ss);

cout << dur1 << endl;

getchar();

return 0;

}


Ключевое слово operator и сам оператор вывода (<<). На вход он принимает поток и структуру типа Duration.

Оператор должен возвращать ссылку на поток, то есть ostream&. Почему?

Разберем простейший вывод:

cout << "Hello" << " world";

Первую часть команды можно представить как:

operator<<(cout, "Hello");

Оператора принимает на вход выходной поток и строку для вывода. Стобы корректно отработал следующий оператор, необходимо принять возвращаемое значение (поток) от первого оператора и передать его второму:

operator<<(operator<<(cout, "Hello"), " world");

Такая команда выведет в консоль Hello world;


Аналогичным образом можно перегрузить оператор ввода >>:


#include <iostream>

#include <sstream>

#include <iomanip>


using namespace std;


struct Duration

{

int hour;

int min;

};


istream& operator>>(istream& stream, Duration& dur)

{

stream >> dur.hour;

stream.ignore(1); //ignore ':'

stream >> dur.min;

return stream;

}


ostream& operator<<(ostream& stream, const Duration& dur)

{

stream << setfill('0');

stream << setw(2) << dur.hour << ':'

<< setw(2) << dur.min;

}


int main()

{

stringstream dur_ss("01:05");

Duration dur1;

dur_ss >> dur1;

cout << dur1 << endl;

getchar();

return 0;

}


Создаем объект типа Duration и передаем в него поток dur_ss, в котором содержится время.


Продолжим по этому же примеру. Напишем функцию сравнения, принимающую два объекта типа Duration и возвращающее true, если первый меньше второго:


bool CompareDurations(const Duration& lhs, const Duration& rhs)

{

if(lhs.hour == rhs.hour)

return lhs.min < rhs.min;

return lhs.hour < rhs.hour;

}


В main() запишем:


Duration dur1 {1, 12};

Duration dur2 {1, 13};

cout << boolalpha << CompareDurations(dur1, dur2) << endl;


Параметр boolalpha позволяет выводить булевые значения в формате true/false, а не 1/0.

Попробуем перегрузить оператор < (меньше), чтобы не вызывать функцию, а использовать его:


bool operator < (const Duration& lhs, const Duration& rhs)

{

if(lhs.hour == rhs.hour)

return lhs.min < rhs.min;

return lhs.hour < rhs.hour;

}


cout << boolalpha << (dur1 < dur2) << endl;


Теперь оператор сравнения отрабатывает корректно с двумя структурами.


Примеры реализации перегрузки операторов внутри класса, представляющего собой целочисленные дроби. P - числитель, Q - знаменатель.


class Rational {

public:

Rational() {

p = 0;

q = 1;

}


Rational(int numerator, int denominator) {

Initialize(numerator, denominator);

}


void Initialize(const int& n, const int& d)

{

p = n;

q = d;

}


int Numerator() const {

return p;

}


int Denominator() const {

return q;

}


const bool operator == (const Rational& a) const

{

if((a.p == p))

return true;

else return false;

}

const bool operator > (const Rational& a) const

{

if((p * a.q) > (q * a.p))

return true;

else return false;

}

const bool operator < (const Rational& a) const

{

if((p * a.q) < (q * a.p))

return true;

else return false;

}

Rational operator + (const Rational& x)

{

Rational result;

if(x.q == q)

{

result.p = x.p + p;

result.q = x.q;

}

else

{

result.p = (x.p * q) + (p * x.q);

result.q = x.q * q;

}

result.SignedFactional();

return result;

}

Rational operator - (const Rational& x)

{

Rational result;

if(x.q == q)

{

result.p = p - x.p;

result.q = x.q;

}

else

{

result.p = (p * x.q) - (x.p * q);

result.q = x.q * q;

}

result.SignedFactional();

return result;

}

Rational operator * (const Rational& x)

{

Rational result;

result.p = x.p * p;

result.q = x.q * q;

result.SignedFactional();

return result;

}

Rational operator / (const Rational& x)

{

Rational result;

result.p = x.q * p;

result.q = x.p * q;

result.SignedFactional();

return result;

}

private:

int p;

int q;

};




istream& operator >> (istream& stream, Rational& r)

{

int p_t, q_t;

stream >> p_t;

stream.ignore(1); //ignore '/'

stream >> q_t;

r.Initialize(p_t, q_t);

return stream;

}


ostream& operator << (ostream& stream, const Rational& r)

{

stream << r.Numerator() << '/' << r.Denominator();

return stream;

}







 
MyTetra Share v.0.53
Яндекс индекс цитирования