Выбрать главу

 protected:

  double x, y;

 public:

  void set_dim(double i, double j) {

   x = i;

   у = j;

  }

  virtual void show_area() {

   cout << "Для этого класса выражение вычисления ";

   cout << "площади не определено.\n";

  }

};

class triangle : public figure {

 public:

  void show_area() {

   cout << "Треугольник с высотой ";

   cout << x << " и основанием " << у;

   cout << " имеет площадь ";

   cout << х * 0.5 * у << ".\n";

  }

};

class rectangle : public figure {

 public:

  void show_area() {

   cout << "Прямоугольник с размерами ";

   cout << x << " x " << у;

   cout << " имеет площадь ";

   cout << х * у << ".\n";

  }

};

int main()

{

 figure *р; // создаем указатель на базовый тип

 triangle t; // создаем объекты производных типов

 rectangle r;

 р = &t;

 p->set_dim(10.0, 5.0);

 p->show_area();

 р = &r;

 p->set_dim(10.0, 5.0);

 p->show_area();

 return 0;

}

Вот как выглядят результаты выполнения этой программы.

Треугольник с высотой 10 и основанием 5 имеет площадь 25.

Прямоугольник с размерами 10 х 5 имеет площадь 50.

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

Как вы думаете, используя объявление класса figure, можно вывести класс circle для вычисления площади круга по заданному значению радиуса? Ответ: да. Для этого достаточно создать новый производный тип, который бы вычислял площадь круга. Могущество виртуальных функций опирается на тот факт, что программист может легко вывести новый тип, который будет разделять общий интерфейс с другими "родственными" объектами. Вот, например, как это можно сделать в нашем случае:

class circle : public figure {

 public:

  void show_area() {

   cout << "Круг с радиусом ";

   cout << x;

   cout << " имеет площадь ";

   cout << 3.14 * x * x;

  }

};

Прежде чем опробовать класс circle в "деле", рассмотрим внимательно определение функции show_area(). Обратите внимание на то, что в нем используется только одно значение переменной x, которая должна содержать радиус круга. (Вспомните, что площадь круга вычисляется по формуле пR2.) Однако согласно определению функции set_dim() в классе figure ей передается два значения, а не одно. Поскольку классу circle не нужно второе значение, то что мы можем предпринять?

Есть два способа решить эту проблему. Первый (и одновременно наихудшим) состоит в том, что мы могли бы, работая с объектом класса circle, просто вызывать функцию set_dim(), передавая ей в качестве второго параметра фиктивное значение. Основной недостаток этого метода — отсутствие четкости в задании параметров и необходимость помнить о специальном исключении, которое нарушает действие принципа: "один интерфейс, множество методов".

Есть более удачный способ решения этой проблемы, который заключается в предоставлении параметру функции set_dim() значения, действующего по умолчанию. В этом случае при вызове функции set_dim() для круга нужно задавать только радиус. При вызове же функции set_dim() для треугольника или прямоугольника задаются оба значения. Ниже показана программа, в которой реализован этот метод.