V
Vadik(R)
Здравствуйте, дорогие форумчане.
Скажу сразу, задание помогаю делать знакомой, и обычно проблем не возникало никаких с её заданиями, но в этот раз.. Я от задания сам стал находится в небольшом шоке.. В общим, хороший такой пробел у меня по абстрактным классам, меня в универе по ним не гоняли ((
Собственно, проблема такая (выложу пока её часть, по мере решения буду код ещё давать).
Итак, задание. В него ещё вникал некоторое время:
Немного погуглив, приступил к реализации.
Вот, что пока вышло.
Код pair.h:
Код pair.cpp:
Код fraction.h:
Код fraction.cpp:
Код main.cpp:
Теперь мои комментарии к коду и вопросы. То, что write - это метод, а не оператор, << пишущий в ostream - опустим, примут, не сложно переделать.
Насчёт использования
вообще не уверен, просто спустя большое количество просиженных часов, и перепробовав методом перебора кучу способов так, чтобы заработало, как-то сами собой эти строчки у меня получились. Возможно они и не нужны, жду подсказок от гуру, как нужно делать такие задания
Далее, собственно вопросы.
Наткнулся на такой полезный учебник, который и читал. А именно, вот:
Сделал всё по аналогии, но почему-то у меня не работает участок кода, как у них:
Он не подставляет дальше всё (закоменченную строчку) в
Почему - не в курсе, но он рекурсивно вызывает сам себя и вылетает (для того cout и поставил )
Это первый такой, основной вопрос. Я его решил приведением типа (но это же не профессионально, да?)
Тогда встал второй вопрос.
Если я создаю просто объект, то он не всегда корректно потом выводит значения. Было return Fraction(5, 6);, c->write() в коде нормально работал (т. е. всегда писал 5 / 6). А вот на дробь 10 / 8 он почему-то стал выводить совсем другие значения.
return *new Fraction....
В общем, возврат значение указателя - в этом случае сложение происходит корректно. Но есть утечка памяти, что есть очень плохо. Проверяется:
Вот в таком случае явно видно, что занятая оперативная память около 400 Мб.
В общем, любые комментарии, помощь - приветствуются. Мне это важно не только, чтобы знакомой сделать лабу, а чисто для себя.
В олимпиадном программировании и собственном быдлокодинге абстрактные классы никак мне не пригодились, а вот при устройстве на работу, чувствую, вполне возможны вопросы по абстрактным классам на собеседовании. Заранее всем спасибо
P.S. Для удобства добавил сам проект Посмотреть вложение test.rar
Скажу сразу, задание помогаю делать знакомой, и обычно проблем не возникало никаких с её заданиями, но в этот раз.. Я от задания сам стал находится в небольшом шоке.. В общим, хороший такой пробел у меня по абстрактным классам, меня в универе по ним не гоняли ((
Собственно, проблема такая (выложу пока её часть, по мере решения буду код ещё давать).
Итак, задание. В него ещё вникал некоторое время:
Во-первых, для меня было уже откровением, что есть чисто абстрактные методы.Реализации всех классов, а также основная функция программы, должны быть разнесены по различным файлам исходного текста и использовать соответствующие заголовочные файлы.
В следующих заданиях требуется реализовать абстрактный базовый класс, определив в нем чистые виртуальные функции. Эти функции определяются в производных классах. В базовых классах должны быть объявлены чистые виртуальные функции ввода/вывода, которые реализуются в производных классах.
Вызывающая программа должна продемонстрировать все варианты вызова виртуальных функций с помощью указателей на базовый класс. Написать функцию вывода, получающую параметры базового класса по ссылке и демонстрирующую виртуальный вызов.
Создать абстрактный базовый класс Pair с виртуальными арифметическими операциями. Создать производные классы Money (задание 1.24) и Fraction (задание 1.35).
Задание 1.35
Создать класс Fraction для работы с дробными числами. Число должно быть представлено двумя полями: целая часть - длинное целое со знаком, дробная часть - беззнаковое короткое целое. Реализовать арифметические операции сложения, вычитания, умножения и операции сравнения.
Немного погуглив, приступил к реализации.
Вот, что пока вышло.
Код pair.h:
C++:
class Pair
{
public:
Pair();
~Pair();
virtual void read() = 0;
virtual void write() = 0;
virtual Pair& operator=(Pair &other) = 0;
virtual Pair& operator+(Pair &other) = 0;
};
C++:
#include "pair.h"
Pair::Pair()
{
}
Pair::~Pair()
{
}
C++:
#include "pair.h"
class Fraction : public Pair
{
public:
Fraction();
Fraction(Fraction &other);
Fraction(long numerator, long denominator);
~Fraction();
void read();
void write();
virtual Pair& operator=(Pair &other);
virtual Pair& operator+(Pair &other);
protected:
virtual Pair& operator=(Fraction &other);
virtual Pair& operator+(Fraction &other);
private:
unsigned short denominator;
long numerator;
};
C++:
#include <iostream>
#include "fraction.h"
using namespace std;
long gcd(long a, long b)
{
return b ? gcd(b, a % b) : a;
}
void normalize(long &numerator, long &denominator)
{
long n;
if (denominator < 0)
{
numerator = -numerator;
denominator = -denominator;
}
if (numerator == 0 || denominator == 0)
{
denominator = 1;
}
n = gcd(abs(numerator), abs(denominator));
numerator /= n;
denominator /= n;
}
Fraction::Fraction()
{
numerator = 0;
denominator = 1;
}
Fraction::Fraction(Fraction &other)
{
this->numerator = other.numerator;
this->denominator = other.denominator;
}
Fraction::Fraction(long numerator, long denominator)
{
normalize(numerator, denominator);
this->numerator = numerator;
this->denominator = denominator;
}
Fraction::~Fraction()
{
}
void Fraction::read()
{
cout << "Введите числитель: ";
cin >> numerator;
cout << "Введите знаменатель: ";
cin >> denominator;
}
void Fraction::write()
{
cout << numerator << " / " << denominator;
}
Pair& Fraction::operator=(Pair &other)
{
cout << "operator=Pair" << endl;
*this = *(Fraction*)&other;
return *this;
}
Pair& Fraction::operator+(Pair &other)
{
cout << "operator+Pair" << endl;
//return other + *this; - it doesn't work Oo
return *(Fraction*)&other + *this;
}
Pair& Fraction::operator=(Fraction &other)
{
cout << "operator=Fraction" << endl;
this->numerator = other.numerator;
this->denominator = other.denominator;
return *this;
}
Pair& Fraction::operator+(Fraction &other)
{
cout << "operator+Fraction" << endl;
//return Fraction(10, 8);
return *(new Fraction(this->numerator * other.denominator + other.numerator * this->denominator, this->denominator * other.denominator));
}
C++:
#include <cmath>
#include <iostream>
#include <locale>
#include "fraction.h"
using namespace std;
int main()
{
Pair* a;
Pair* b;
Pair* c;
cout.setf(ios::fixed);
cout.precision(2);
setlocale(LC_ALL, "Rus");
a = new Fraction();
a->read();
b = new Fraction();
b->read();
c = new Fraction();
*c = *a + *b;
cout << "c = ";
c->write();
cout << endl;
delete a;
delete b;
delete c;
return 0;
}
Теперь мои комментарии к коду и вопросы. То, что write - это метод, а не оператор, << пишущий в ostream - опустим, примут, не сложно переделать.
Насчёт использования
C++:
virtual Pair& operator=(Pair &other);
virtual Pair& operator=(Fraction &other);
Далее, собственно вопросы.
Наткнулся на такой полезный учебник, который и читал. А именно, вот:
Ссылка скрыта от гостей
Сделал всё по аналогии, но почему-то у меня не работает участок кода, как у них:
C++:
Pair& Fraction::operator+(Pair &other)
{
cout << "operator+Pair" << endl;
//return other + *this; - it doesn't work Oo
return *(Fraction*) &other + *this;
}
C++:
Pair& Fraction::operator+(Fraction &other)
Это первый такой, основной вопрос. Я его решил приведением типа (но это же не профессионально, да?)
Тогда встал второй вопрос.
C++:
Pair& Fraction::operator+(Fraction &other)
{
cout << "operator+Fraction" << endl;
//return Fraction(10, 8);
return *(new Fraction(this->numerator * other.denominator + other.numerator * this->denominator, this->denominator * other.denominator));
}
return *new Fraction....
В общем, возврат значение указателя - в этом случае сложение происходит корректно. Но есть утечка памяти, что есть очень плохо. Проверяется:
C++:
for (unsigned int i = 0; i < 10000000; i++)
{
*c = *a + *b;
}
//для паузы
a->read();
В общем, любые комментарии, помощь - приветствуются. Мне это важно не только, чтобы знакомой сделать лабу, а чисто для себя.
В олимпиадном программировании и собственном быдлокодинге абстрактные классы никак мне не пригодились, а вот при устройстве на работу, чувствую, вполне возможны вопросы по абстрактным классам на собеседовании. Заранее всем спасибо
P.S. Для удобства добавил сам проект Посмотреть вложение test.rar