Домашнее задание №10. Абстрактные классы, полиморфизм

Доделайте задачи классной работы, включая дополнительные.

  1. Создать абстрактный класс Shape c виртуальными методами Area() и Perimeter();
    class Shape
    {
    public:
    	virtual double Area() const = 0;
    	virtual double Perimeter() const = 0;
    	
    	// virtual destructor
    	virtual ~Shape() {};
    };

    Виртуальная функция — это функция-член, которую предполагается переопределить в производных классах. При ссылке на объект производного класса с помощью указателя или ссылки на базовый класс можно вызвать виртуальную функцию для этого объекта и выполнить версию функции производного класса.

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

    Виртуальная функция без реализации называется чисто виртуальной. Её синтаксис 

    virtual <тип> <имя> (<список параметров>) = 0; 

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

  2. Создать класс Circle - открытый наследник Shape. Он имеет закрытое поле типа double - радиус и метод
    void setRadius(double);
    который задаёт значение радиуса. Также класс должен иметь конструктор

    Circle(double = 0.0);
    с параметром типа double, который обращается к методу setRadius. Также он должен переопределять виртуальные методы класса Shape так, чтобы они возвращали площадь и периметр круга. Заголовки перегруженных функций в файле Circle.h выглядят следующим образом:
    double Area() const override;
    double Perimeter() const override;
    Ключевое слово override указывает, что элемент переопределяет член базового класса.
  3. Создать класс Rectangle (прямоугольник) - открытый наследник Shape. Он имеет два закрытых поля типа double - length и width (длина и ширина). Создать два открытых виртуальных метода с реализацией 

    virtual void setLength(double);
    virtual void setWidth(double);
    для задания длины и ширины, соответственно. Также он должен иметь конструктор
    Rectangle(double = 0.0, double = 0.0);
    с двумя параметрами типа double, который обращается к setLength и setWidth. Также класс должен переопределять Area() и Perimeter() так, чтобы они возвращали площадь и периметр прямоугольника.
  4. Создать класс Square (квадрат) - наследник Rectangle. Он должен иметь конструктор, который принимает один параметр типа double и вызывает конструктор базового класса

    Square(double width):Rectangle(width, width) {}
    
    Также нужно переопределить методы setLength() и setWidth() таким образом, чтобы они одновременно изменяли значения длины и ширины так, чтобы они оставались одинаковыми (подсказка: перегруженные методы могут вызывать методы базового класса, например Rectangle::setLength(width);).
  5. В файле с функцией main() создать функцию

    double averageArea(const vector<shape*> &v);
    которая принимает ссылку на вектор указателей на объект типа Shape и возвращает среднюю площадь фигур, указатели на которые содержатся в векторе. 
  6. В функцию main() добавить следующий код:
    	vector<shape*> v;
    	v.push_back(new Circle(1));
    	v.push_back(new Circle(2));
    	v.push_back(new Circle(3));
    	v.push_back(new Rectangle(1, 2));
    	v.push_back(new Rectangle(2, 3));
    	v.push_back(new Rectangle(3, 4));
    	v.push_back(new Square(1));
    	v.push_back(new Square(2));
    	v.push_back(new Square(3));
    	cout << "The average area of all these shapes equals " << averageArea(v) << endl;
    
    По ссылке - UML-диаграмма классов