Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.82/11: Рейтинг темы: голосов - 11, средняя оценка - 4.82
17 / 17 / 6
Регистрация: 10.12.2013
Сообщений: 740
1

Используется ли полиморфизм в данной программе для вычисления площадей различных фигур?

27.07.2017, 11:13. Показов 1936. Ответов 21
Метки нет (Все метки)

Всем привет!

Изучаю полиморфизм. Интересная тема, меня прям затянуло и я решил поупражняться, написав программу для вычисления площадей различных фигур. Вот код:

Shape.h
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#pragma once
 
class Shape
{
protected:
    double area;
 
public:
    Shape();
    virtual ~Shape();
 
    virtual void countArea() = 0;
    virtual double getArea() const = 0;
};


Shape.cpp
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
#include "stdafx.h"
#include "Shape.h"
 
 
Shape::Shape() : area(0)
{}
 
Shape::~Shape()
{}


TwoDimensionalShape.h
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
#pragma once
#include "Shape.h"
 
class TwoDimensionalShape : public Shape
{
public:
    TwoDimensionalShape();
    virtual ~TwoDimensionalShape();
 
    virtual void countArea() = 0;
    virtual double getArea() const = 0;
};


TwoDimensionalShape.cpp
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
#include "stdafx.h"
#include "TwoDimensionalShape.h"
 
 
TwoDimensionalShape::TwoDimensionalShape() : Shape()
{}
 
TwoDimensionalShape::~TwoDimensionalShape()
{}


Triangle.h
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#pragma once
#include "TwoDimensionalShape.h"
 
class Triangle : public TwoDimensionalShape
{
protected:
    double a, b, c, h;
 
public:
    Triangle();
    virtual ~Triangle();
 
    void setValues(double, double, double, double);
    bool check() const;
    void countAreaByHeron();
 
    virtual void countArea() = 0;
    virtual double getArea() const = 0;
};


Triangle.cpp
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include "stdafx.h"
#include "Triangle.h"
#include <cmath>
 
 
Triangle::Triangle() : TwoDimensionalShape(), a(0), b(0), c(0), h(0)
{}
 
Triangle::~Triangle()
{}
 
void Triangle::setValues(double a, double b, double c, double h){
    this->a = a;
    this->b = b;
    this->c = c;
    this->h = h;
}
 
bool Triangle::check() const{
    if(((a + b) > c) && ((b + c) > a) && ((a + c) > b))
        return true;
    else
        return false;
}
 
void Triangle::countAreaByHeron(){
    double p;
 
    p = (a + b + c) / 2;
 
    area = sqrt(p * (p - a) * (p - b) * (p - c));
}


RightTriangle.h
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#pragma once
#include "Triangle.h"
 
class RightTriangle : public Triangle
{
public:
    RightTriangle();
    virtual ~RightTriangle();
 
    bool checkPyfagor() const;
 
    virtual void countArea();
    virtual double getArea() const;
};


RightTriangle.cpp
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "stdafx.h"
#include "RightTriangle.h"
#include <cmath>
 
 
RightTriangle::RightTriangle() : Triangle()
{}
 
RightTriangle::~RightTriangle()
{}
 
void RightTriangle::countArea(){
    area = pow((b * c), -1);
}
 
bool RightTriangle::checkPyfagor() const{
    if((pow(b, 2) + pow(c, 2)) == pow(a, 2))
        return true;
    else
        return false;
}
 
double RightTriangle::getArea() const{
    return area;
}


EquilateralTriangle.h
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#pragma once
#include "Triangle.h"
 
class EquilateralTriangle : public Triangle
{
public:
    EquilateralTriangle();
    virtual ~EquilateralTriangle();
 
    bool checkSides() const;
 
    virtual void countArea();
    virtual double getArea() const;
};


EquilateralTriangle.cpp
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "stdafx.h"
#include "EquilateralTriangle.h"
#include <cmath>
 
 
EquilateralTriangle::EquilateralTriangle() : Triangle()
{}
 
EquilateralTriangle::~EquilateralTriangle()
{}
 
bool EquilateralTriangle::checkSides() const{
    if((a == b) && (b == c))
        return true;
    else
        return false;
}
 
void EquilateralTriangle::countArea(){
    area = pow((a * h), -1);
}
 
double EquilateralTriangle::getArea() const{
    return area;
}


main.cpp
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include "stdafx.h"
#include "Shape.h"
#include "TwoDimensionalShape.h"
#include "Triangle.h"
#include "RightTriangle.h"
#include "EquilateralTriangle.h"
 
#include <iostream>
#include <vector>
#include <typeinfo>
using namespace std;
 
int main()
{
    double side1, side2, side3, height;
 
    RightTriangle rt;
    EquilateralTriangle et;
 
    cout << "Input sides and height of triangle №1:" << endl;
    cin >> side1 >> side2 >> side3 >> height;
    cout << endl << endl;
 
    rt.setValues(side1, side2, side3, height);
 
    cout << "Input sides and height of triangle №2:" << endl;
    cin >> side1 >> side2 >> side3 >> height;
    cout << endl << endl;
 
    et.setValues(side1, side2, side3, height);
    
    vector<Shape*>figures(2);
 
    figures[0] = &rt;
    figures[1] = &et;
 
    for(size_t i = 0;i < figures.size();i++){
        RightTriangle* dPtr3 = dynamic_cast<RightTriangle*> (figures[i]);
        EquilateralTriangle* dPtr5 = dynamic_cast<EquilateralTriangle*> (figures[i]);
 
        if(dPtr3 != 0){
            if(rt.check()){
                if(dPtr3->checkPyfagor()){
                    figures[i]->countArea();
                    cout << "Right triangle's square = " << figures[i]->getArea() << endl;
                }
                else
                    cout << "Triangle number 1 isn't right!" << endl;
            }
            else
                cout << "Triangle number 1 doesn't exist!" << endl;
        }
 
        else if(dPtr5 != 0){
            if(et.check()){
                if(dPtr5->checkSides()){
                    figures[i]->countArea();
                    cout << "Equilateral triangle's square = " << figures[i]->getArea() << endl;
                }
                else
                    cout << "Triangle number 2 isn't equilateral!" << endl;
            }
            else
                cout << "Triangle number 2 doesn't exist!" << endl;
        }
    }
 
    cout << endl;
 
    for(size_t i = 0;i < figures.size();i++){
        figures[i]->~Shape();
    }
 
    system("pause");
    return 0;
}



Программа далеко не полная.

Вопрос следующий: присутствует ли здесь, в моём коде, полиморфизм? Ответьте, профессионалы. Ибо я начитался статей про него на Хабре, так там почти сплошная критика по поводу кодов с полиморфизмом. Вот я и подумал...может, я тоже не так понял эту парадигму и неправильно ее использую...
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
27.07.2017, 11:13
Ответы с готовыми решениями:

Составить программу вычисления площадей различных фигур
Составить программу вычисления площадей различных фигур: p*l,если k =1 p*h/2,если k=2 S=...

Составить программу вычисления площадей различных геометрических фигур
Составить программу вычисления площадей различных геометрических фигур:

Программа для вычисления площадей плоских фигур
Здравствуйте, мне надо сделать курсовую по теме &quot;Программа для вычисления площадей плоских фигур....

Разработать класс, содержащий методы вычисления параметров плоских и объёмных фигур, а именно длин, площадей, объёмов, площадей поверхности
Тема: Программирование вычислительных алгоритмов. Создание класса для вычисления параметров плоских...

21
961 / 855 / 299
Регистрация: 27.07.2012
Сообщений: 2,393
27.07.2017, 11:40 2
Лучший ответ Сообщение было отмечено Sh@dow777 как решение

Решение

Цитата Сообщение от Sh@dow777 Посмотреть сообщение
Вопрос следующий: присутствует ли здесь, в моём коде, полиморфизм?
Присутствует, но не совсем правильно. Если для работы с полиморфными объектами приходится делать dynamic_cast, то, вероятнее всего, уже что-то пошло не так. Должно быть всё просто, типа:
C++
1
2
3
4
vector<Shape*> figures;
figures.push_back(new Triangle);
figures.push_back(new Square);
for_each(figures.begin(), figures.end(), mem_fun(&Shape::getArea));
1
зомбяк
1556 / 1195 / 339
Регистрация: 14.05.2017
Сообщений: 3,882
27.07.2017, 14:20 3
Нужно добавить функцию, которая бы определяла, что именно делать в цикле проверки. То есть virtual int Triangle::getCheckWay() = 0;
Тогда бы всё было просто

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
for(size_t i = 0;i < figures.size();i++){
        RightTriangle* dPtr3 = dynamic_cast<RightTriangle*> (figures[i]);
        EquilateralTriangle* dPtr5 = dynamic_cast<EquilateralTriangle*> (figures[i]);
 
       if(figures[i].check()){
               int check_way = figures[i]->getCheckWay();
               bool correct = false;
               figures[i]->countArea();
 
               switch(check_way)
               {
               case 0:
                     if( (static_cast<RightTriangle*>(figures[i]))->checkPyfagor() )
                           cout << "Right triangle's square = " << figures[i]->getArea() << endl;
                     else
                           cout << "Triangle number "<< i <<" isn't right!" << endl;
 
                     break;
 
               case 1:
                     if( (static_cast<EquilateralTriangle*>(figures[i]))->checkSides() )
                           cout << "Equilateral triangle's square = " << figures[i]->getArea() << endl;
                     else
                           cout << "Triangle number 2 isn't equilateral!" << endl;
                     break;
 
               default:;
               }
            }
            else
                cout << "Triangle number "<< i <<" doesn't exist!" << endl;
        }
    }
1
Заблокирован
27.07.2017, 14:32 4
Цитата Сообщение от Sh@dow777 Посмотреть сообщение
Изучаю полиморфизм.
Ты явно делаешь это неправильно.

Цитата Сообщение от Sh@dow777 Посмотреть сообщение
Интересная тема, меня прям затянуло и я решил поупражняться, написав программу для вычисления площадей различных фигур.
Фигуры — как раз то место, где полиморфизм не работает. По крайней мере тот, что основывается на наследовании и виртуальных функциях, а не ad-hoc.
Что он не работает — можно видеть по сабтайпам треугольника. Они требуют ручной проверки инвариантов и EquilateralTriangle может быть запросто не равносторонним треугольником. Смысла тогда в этом классе — ноль.


Другой пример, которым обычно иллюстрируют полиморфизм — это животные. Ну там кошечка говорит "Мяу", а собачка "Гав" и они делают это переопределяя метод Say их общего предка Animal. В общем, это тоже хреновый пример полиморфизма.
1
17 / 17 / 6
Регистрация: 10.12.2013
Сообщений: 740
27.07.2017, 23:48  [ТС] 5
daun-autist, В вашем примере если задать в классах кошечки и собачки элемент данных "Количество лап", и ввести число, большее или меньшее, чем 4, то это тоже будет ни кошечка, ни собачка)

Более лучшим примером будут шахматы, наверно...с
Код
virtual void move() = 0
0
Заблокирован
27.07.2017, 23:51 6
Цитата Сообщение от Sh@dow777 Посмотреть сообщение
В вашем примере если задать в классах кошечки и собачки элемент данных "Количество лап", и ввести число, большее или меньшее, чем 4, то это тоже будет ни кошечка, ни собачка)
А я что, сказал что кошечки и собачки это хороший пример полиморфизма?
Цитата Сообщение от daun-autist Посмотреть сообщение
В общем, это тоже хреновый пример полиморфизма.

Короче: равносторонний треугольник не является подтипом треугольника. И квадрат не является подтипом прямоугольника. Это хрестоматийные примеры неправильного использования полиморфизма.
0
17 / 17 / 6
Регистрация: 10.12.2013
Сообщений: 740
27.07.2017, 23:59  [ТС] 7
John Prick, Да это я знаю. Я просто читаю книгу Дейтелов + инет. В Дейтелах просто рассказывается про динамик каст, и я решил попрактиковаться.

В принципе, думаю, если в векторе достаточно большое количество указателей(100+, к примеру), и в определенный момент понадобится работать с каким-то из них(с определенным), то динамик каст может пригодиться.
0
Заблокирован
28.07.2017, 00:05 8
Цитата Сообщение от Sh@dow777 Посмотреть сообщение
В вашем примере если задать в классах кошечки и собачки элемент данных "Количество лап", и ввести число, большее или меньшее, чем 4, то это тоже будет ни кошечка, ни собачка
Что, собачка, которой трамваем отрезало одну лапу — уже не собачка?
0
17 / 17 / 6
Регистрация: 10.12.2013
Сообщений: 740
28.07.2017, 00:06  [ТС] 9
daun-autist, Квадрат и прямоугольник являются подтипами четырехугольника. Но и тут можно сделать проверку на количество углов

С типами треугольников я просто потренировался. Типа интерфейс(Shape), потом наследовать еще один интерфейс(TwoDimensionalShape), потом наследовать абстрактный класс(Triangle), ну и под конец три обычных класса(три типа треугольников).
0
Заблокирован
28.07.2017, 00:09 10
Цитата Сообщение от Sh@dow777 Посмотреть сообщение
Квадрат и прямоугольник являются подтипами четырехугольника.
И какие же методы будут у их базового класса — четырёхугольника? Какие инварианты?
0
17 / 17 / 6
Регистрация: 10.12.2013
Сообщений: 740
28.07.2017, 00:25  [ТС] 11
daun-autist,
Цитата Сообщение от daun-autist Посмотреть сообщение
Что, собачка, которой трамваем отрезало одну лапу — уже не собачка?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Dog
{
    protected:
          int countLegs;
    
    public:
        Dog() : countLegs(4){};
        virtual ~Dog();
 
        virtual bool checkLegs() const = 0;
}
 
class DogInvalid : public Dog
{
    public:
        DogInvalid(int legs) : Dog(), countLegs(legs){};
        virtual ~DogInvalid();
 
        virtual bool checkLegs() const{ return (countLegs < 4);};
}
 
class DogCyborg : public Dog
{
    public:
        DogCyborg(int legs) : Dog(), countLegs(legs){};
        virtual ~DogCyborg();
 
        virtual bool checkLegs() const{ return (countLegs > 4);};
}
0
Заблокирован
28.07.2017, 00:31 12
Sh@dow777, а если она сначала была обычной собачкой, а потом ей отрезало? Типами это не выразить. Ну по крайней мере C++-типами.
0
17 / 17 / 6
Регистрация: 10.12.2013
Сообщений: 740
28.07.2017, 00:39  [ТС] 13
daun-autist,
Цитата Сообщение от daun-autist Посмотреть сообщение
И какие же методы будут у их базового класса — четырёхугольника? Какие инварианты?
C++
1
2
virtual void countPerimeter() = 0;
       virtual void countArea() = 0;
Насчет периметра можно, конечно, сказать, что "просто сложи все стороны и всё". Но можно использовать разные формулы. У квадрата и ромба 4а, у прямоугольника - 2(a + b).

С площадью тоже самое. Квадрат и прямоугольник - a * b, у ромба другое.
0
Заблокирован
28.07.2017, 00:42 14
Sh@dow777, а что в этих двух методах такого, что делает класс с ними четырёхугольником?
0
17 / 17 / 6
Регистрация: 10.12.2013
Сообщений: 740
28.07.2017, 01:01  [ТС] 15
daun-autist, Я так полагаю, формулы, использующиеся в этих методах. Вряд ли посчитаешь площадь треугольника формулами четырехугольников.

А что, по вашему, в методе Say такого, что делает класс Animal с ним животным? Говорить "мяу" и "гав" и люди могут.
0
Заблокирован
28.07.2017, 01:07 16
Цитата Сообщение от Sh@dow777 Посмотреть сообщение
Я так полагаю, формулы, использующиеся в этих методах
Их не видно снаружи. И связи между ними тоже нет, так что и о каких-то инвариантах говорить сложно.

Класс для эллипсов тоже может иметь эти методы.
0
17 / 17 / 6
Регистрация: 10.12.2013
Сообщений: 740
28.07.2017, 01:23  [ТС] 17
daun-autist, Ну если четырехугольник - это не самый-самый базовый класс, то можно в класс Фигура ввести количество углов и функцию для проверки. Если количество углов = 3 - треугольник, 4 - четырехугольник, 0 - вообще какая-нибудь окружность.

Если это самый-самый базовый класс, то в него включить кол-во углов и проверку - если меньше или больше 4, не четырехугольник. А вообще, я думаю, это должно быть само собой разумеющееся:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Triangle
{
    private:
        int angles;
 
    public:
        Triangle() : angles(3){};
}
 
class Rectangle
{
    private:
        int angles;
 
    public:
        Rectangle() : angles(4){};
}
Добавлено через 54 секунды
Кстати, мы с вами в дебри ушли
0
961 / 855 / 299
Регистрация: 27.07.2012
Сообщений: 2,393
28.07.2017, 11:17 18
Цитата Сообщение от Sh@dow777 Посмотреть сообщение
В принципе, думаю, если в векторе достаточно большое количество указателей(100+, к примеру), и в определенный момент понадобится работать с каким-то из них(с определенным), то динамик каст может пригодиться.
Без разницы сколько там указателей, 100+ или 100500+. Если поведение производных классов не удаётся выразить через имеющиеся виртуальные функции базового, то значит, либо иерархия классов спроектирована неверно, либо вообще полиморфизм здесь неуместен. Примеры с фигурами и животными это демонстрируют.
1
Любитель чаепитий
3671 / 1747 / 543
Регистрация: 24.08.2014
Сообщений: 5,888
Записей в блоге: 1
28.07.2017, 12:29 19
Цитата Сообщение от Sh@dow777 Посмотреть сообщение
0 - вообще какая-нибудь окружность.
и как тогда отличать эллипсис от круга?
и это только если не брать 3д-фигуры.
0
зомбяк
1556 / 1195 / 339
Регистрация: 14.05.2017
Сообщений: 3,882
28.07.2017, 12:48 20
Цитата Сообщение от GbaLog- Посмотреть сообщение
как тогда отличать эллипсис от круга?
По эксцентриситету - https://ru.wikipedia.org/wiki/Эксцентриситет
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
28.07.2017, 12:48

Полиморфизм. Виртуальные методы. Найти максимальную из площадей фигур
Составить программу с одним родительским классом и двумя потомками. Потомки должны содержать...

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

Разработать библиотеку математических функций для вычисления площадей плоских геометрических фигур
Разработать библиотеку математических функций для вычисления площадей плоских геометрических фигур...

Вычисление площадей различных геометрических фигур
Составить программу вычисления площадей различных геометрических фигур


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru