Описание класса дробей
Опишем класс fraction, реализующий представление дробей, а также операторы, которые к ним можно применять #include <iostream> using namespace std; class fraction{ public: int numerator,denominator; //числительизнаменатель fraction(); //конструкторпоумолчанию fraction(int x, int y); //конструктор по двум числам fraction(int x); //конструктор по одному числу fraction(const fraction& op); //конструкторкопирования const fraction operator+(const fraction& op); //сложение const fraction operator=(const fraction& op); //присваивание //вводивывод friend ostream& operator<<(ostream& os, const fraction& op); friend istream& operator>>(istream& is, fraction& op);//ввод private: fraction reduce(); //сокращениедроби } Конструкторы класса дробей Конструктор, принимающий один аргумент — ссылку на константный объект такого же типа — называется конструктором копирования (copyconstructor). Такой конструктор должен инициализировать создаваемый объект таким образом, чтобы он стал копией оригинального объекта. Такой конструктор так же может быть сгенерирован автоматически, если это возможно и есть такая необходимость. Но реализация по умолчанию (использующая копирование всех объектов-членов) может быть неудовлетворительной. В этом случае можно самостоятельно определить конструктор копирования //конструктор по умолчанию - реализация fraction::fraction(){ numerator=0; denominator=1; } //конструкторподвумцелымчислам - реализация fraction::fraction(int x, int y){ numerator=x; denominator=y; reduce(); } //конструкторпреобразования (поодномуцеломучислу) - реализация fraction::fraction(int x, int y){ numerator=x; denominator=1; } //конструкторкопирования - реализация fraction::fraction(const fraction& op){ numerator=op.numerator; denominator=op.denominator; } Приватный метод reduce() для класса fraction Время от времени при проведении операций с дробями или при вводе значений необходимо выполнять сокращение дроби, которое производится взаимным сокращением числителя и знаменателя дроби на их наибольший общий делитель (НОД). Метод не будет вызываться извне, поэтому он описан в разделе private. Сам НОД найдем методом Евклида, описанном в задаче «Наибольший общий делитель» из главы «Циклы» предыдущей части. fraction fraction::reduce(){ int a=numerator,b=denominator; do{ //находим НОД по методу Евклида if(a>=b){a %=b;} else{b %= a;} } while(a*b>0); numerator/=a+b; //сокращаемчислитель denominator/=a+b; //сокращаемзнаменатель return *this; } Обратите внимание на использование указателя thisпри завершении функции. Он всегда ссылается на текущий объект класса, к которому был применён метод. Арифметические действия с дробями Попробуемперегрузитьоперациисложения, умноженияит.д. для дробей, чтобы с ними можно было работать как с числами стандартных типов. Во-первых, нужно понимать, что оператор – по сути та же функция (метод класса). Тоесть, когдамыкaдобавляемb, происходит a.+(b) Таким образом для функций –членов класса операнд в арифметическом действии должен быть один (второй). К первому мы эту арифметическую операцию применяем как метод. Во-вторых, оба операнда правильно объявить как const, хотя и не обязательно. Это делается для того, чтобы не изменить значения операндов. Проще говоря, чтобы при вычислении a+bзначения самих aи bне изменились. const fraction fraction::operator+(const fraction& p){ fraction r; r.numerator=numerator*p.denominator+p.numerator*denominator; r.denominator=denominator*p.denominator; r.reduce(); returnr; } //операторприсваивания - реализация const fraction fraction::operator=(const fraction& op){ return fraction(op); } Перегрузка операций ввода/вывода для класса Очень важно при создании нового класса, расширяющего возможности языка, чтобы программист мог пользоваться для вывода объектов новых типов привычными операциями, такими как >>и <<. Нам потребуются входные потоки istreamи потоковые операции вывода ostream. Их удобно объявить как дружественные, т.е. не являющиеся членами класса, но имеющие доступ к его методам. ostream& operator<<(ostream& os, const fraction& op){ os<<op.numerator<<'/'<<op.denominator; return os; } istream& operator>>(istream& is, fraction& op){ string s; is>>s; op.numerator=0; op.denominator=0; int i; for(i=0;s[i]!='/';i++){(op.numerator*=10)+=s[i]-’0’;} for(++i;s[i]!='\0';i++){(op.denominator*=10)+=s[i]-’0’;} op.reduce(); returnis; } Программа, демонстрирующая возможности описанного нами класса дробей, может выглядеть следующим образом int main(){ fractiona(2,8),b(a),c,d; //примерыконструкторов fraction x=a+b,y=x; //присваивание cout<<a<<'+'<<b<<'='<<y<<"\nВведите 2 дроби:\n"; cin>>c>>d; //ввод cout<<"Сумма ="<<c+d; //вывод } При этом результаты её работы отобразятся так:
Основы олимпиадного программирования Программирование - как любовь: одно слово, за которым может скрываться бесконечное множество занятий. Фредерик Брукс, "Мифический человеко-месяц"
Популярное: Как распознать напряжение: Говоря о мышечном напряжении, мы в первую очередь имеем в виду мускулы, прикрепленные к костям ... Генезис конфликтологии как науки в древней Греции: Для уяснения предыстории конфликтологии существенное значение имеет обращение к античной... Организация как механизм и форма жизни коллектива: Организация не сможет достичь поставленных целей без соответствующей внутренней... Почему стероиды повышают давление?: Основных причин три... ©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (407)
|
Почему 1285321 студент выбрали МегаОбучалку... Система поиска информации Мобильная версия сайта Удобная навигация Нет шокирующей рекламы |