Апрель 22 2016

Полморфизм?

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

class A {
   public:
     virtual void f() = 0;
}

class B: A{
   public:
     void f() {};
}

class C: A{
   public:
     void f() {};
}

A * b = new B();
A * c = new C();
b->f(); // здесь будет вызываться метод класса B
c->f(); // здесь будет вызываться метод класса C

Вы скажете, м, я могу сделать приведение. Но при этом придется хранить где то информацию о типе класса. И все превращается в такое мессивов

class A {
   public:
     void f(){ std::cout << "abstract virtual methot was called" << std::endl;} int type; A() {type = 1;} } class B: A{ public: void f() {}; B() {type = 2;} } class C: A{ public: void f() {}; C() {type = 3;} } void callF(A* x) { switch (x->type) {
    1:
      x->f();
      break;
    2:
      (B*)x->f();
       break;
    3:
      (C*)x->f();
       break;
    default:
      std::cout << "unknown type " << x->type << std::endl;
  }
}
A * b = new B();
A * c = new C();
callF(b);
callF(c); // здесь будет вызываться метод класса C

И это (если только я не сделал ошибок), будет работать. Более того, в принципе оно в реальном коде так и происходит. Но компилятор просто обладает большей информацией о ситуации в коде. К примеру Java компилятор может сделать не switch, а обычный if, если видит, что там всего два варианта. Либо вообще сделать явный вызов, если и так понятно, что вызывать.

Стоит ли так писать код? Если код пишется на Си, тогда да (более того, некоторые Си программисты почти так и пишут иногда код). Этим занимаются (немного в другом виде, правда), когда пишут на Gtk.

Стоит ли так писать в С++ коде? нет. зачем делать то, что делает компилятор? зачем делать закат Солнца вручную?

Но если кажется, что нужно делать полиморфизм по своему, то может быть нужно выбрать другой языка программирование?

Почему следует использовать полиморфимзм.

пример 1. Пусть есть игра (starcraft, козаки, и подобные). Создается класс “базовый юнит”. От него наследуются все юниты. Все созданные юниты добавляются в один большой массив (вектор, список). Когда нужно отрисовать, то просто в цикле вызываем у всех функция draw и не думаем, а кто у нас там. Каждый объект и так знает, как ему рисоваться.
привет 2. мессенджер типа миранда или квип. Есть куча различных сервисов (аська, жаббер, мейлру). У всех есть контакт лист. Сам мессенджер ничего не знает о сервисах, он просто вызывает функции, а за счет виртуальности и полиморфизма вызываются правильные функции. При этом, если был добавлен новый сервис, то не нужно переписывать весь код, что бы он был в курсе.

Исходник


Метки: ,
Copyright 2017. Все права защищены.

Опубликовано Апрель 22, 2016 master в категории "C++", "Программирование