Виртуелне методе

Виртуелна метода је сопствена (не static) метода основне класе, која може да се замени истоименом методом одговарајуће изведене класе када се позове за објекат који припада изведеној класи. Пријатељске функције неке класе не могу да буду виртуелне за ти класу, јер не припадају тој класи.
Виртуелне методе декларишу се додавањем модификатора
virtual на почетак њихове декларације у основној класи. Приликом поновног декларисања у изведеним класама модификатор virtual се подразумева, те не мора да буде експлицитно наведен.

Декларације дате виртуелне методе у основној и у свим изведеним класама морају да имају исти број и типове параметара и да дају резултат истог типа. Једино у чему се оне разликују је тип објекта за који се позивају. Приликом позивања виртуелне методе показивачем или упућивачем на објекте класе, позиваће се истоимена метода изведене класе на чији објекат у том моменту указује дати показивач или упућивач.

Класе које поседују бар једну виртуелну методу називају се полиморфне класе.
Статички тип показивача наведен је у наредби за дефинисање, зна се већ у време превођења и не може да се промени током извршавања програма.
Динамички тип показивача омогућава позивање одговарајуће виртуелне методе (или за изведену или за основну класу, зависи од текућег објекта).
Виртуелна метода не мора да се дефинише у свим изведеним класама. Ако у некој изведеној класи није дефинисана виртуелна метода позива се метода из основне класе.

Приликом преклапања имена метода све методе се разликују по броју и типовима параметара – статички избор (пре почетка извршавања програма).
Виртуелне методе имају параметре истих типова и дају резултат истог типа. Позвана метода бира се динамички, приликом извршавања програма.
Употреба виртуелних метода обезбеђује објектно оријентисани принцип по коме понашање програма зависи од типа података који се обрађује, а који се назива полиморфизам!

Конструктори не могу бити виртуелне методе. Деструктори могу бити виртуелни.

// tacka.h
// Definicija klase tacaka (Tacka).
#ifndef _tacka_h_
#define _tacka_h_
typedef double Real;                         // Tip za realne vrednosti.
#include <iostream>
using namespace std;
class Tacka {
  Real x, y;                                                // Koordinate.
public:
  Tacka(Real xx=0, Real yy=0) { x = xx; y = yy; }           // Konstruktor.
  Real aps() const { return x; }                            // Apscisa.
  Real ord() const { return y; }                            // Ordinata.
  friend istream& operator>>(istream& ut, Tacka& tt)        // Citanje.
    { return ut >> tt.x >> tt.y; }
  friend ostream& operator<<(ostream& it, const Tacka& tt)  // Pisanje.
    { return it << '(' << tt.x << ',' << tt.y << ')'; }
};
const Tacka ORG;                             // Koordinatni pocetak.
#endif

// figura.h
// Definicija klase geometrijskih figura (Figura).
#ifndef _figura_h_
#define _figura_h_
#include "tacka.h"
class Figura {
  Tacka T;                                        // Teziste figure.
public:
  Figura(const Tacka& tt=ORG): T(tt)  {}          // Konstruktor.
  virtual ~Figura() {}                            // Destruktor.
  virtual Figura* kopija() const =0;              // Stvaranje kopije.
  Figura& postavi(Real xx, Real yy)               // Postavljanje figure.
    { T = Tacka(xx, yy); return *this; }
  Figura& pomeri(Real dx, Real dy)                // Pomeranje figure.
    { T = Tacka(T.aps() + dx, T.ord() + dy); return *this; }
  virtual Real O() const =0;                      // Obim.
  virtual Real P() const =0;                      // Povrsina.
protected:
  virtual void citaj(istream& ut)       { ut >> T; }          // Citanje.
  friend istream& operator>>(istream& ut, Figura& ff)
    { ff.citaj(ut); return ut; }
  virtual void pisi (ostream& it) const { it << "T=" << T; }  // Pisanje.
  friend ostream& operator<<(ostream& it, const Figura& ff)
    { ff.pisi (it); return it; }
};
#endif

// krug.h
// Definicija klase krugova (Krug).
#ifndef _krug_h_
#define _krug_h_
#include "figura.h"
namespace { const Real PI = 3.14159265359; }
class Krug : public Figura {
  Real r;                                         // Poluprecnik.
public:
  explicit Krug(Real rr=1, const Tacka& tt=ORG)   // Konstruktor.
    : Figura(tt) { r = rr; }
  Krug* kopija() const                            // Stvaranje kopije.
    { return new Krug(*this); }
  Real O() const { return 2 * r * PI; }           // Obim.
  Real P() const { return r * r * PI; }           // Povrsina.
private:
  void citaj(istream& ut)                     // Citanje.
  { Figura::citaj(ut); ut >> r; }
void pisi (ostream& it) const {            // Pisanje.
  it << "krug    [";
  Figura::pisi(it);
  it << ", r=" << r << ", O=" << O() << ", P=" << P() << ']';
}
};
#endif

// kvadrat.h
// Definicija klase kvadrata (Kvadrat).
#ifndef _kvadrat_h_
#define _kvadrat_h_
#include "figura.h"
class Kvadrat : public Figura {
  Real a;                                         // Osnovica.
public:
  explicit Kvadrat(Real aa=1, const Tacka& tt=ORG)// Konstruktor.
    : Figura(tt) { a = aa; }
  Kvadrat* kopija() const                         // Stvaranje kopije.
    { return new Kvadrat(*this); }
  Real O() const { return 4 * a; }                // Obim.
  Real P() const { return a * a; }                // Povrsina.
private:
  void citaj(istream& ut){ Figura::citaj(ut); ut >> a; }                        // Citanje.
  void pisi (ostream& it) const{          // Pisanje.
  it << "kvadrat [";
  Figura::pisi(it);
  it << ", a=" << a << ", O=" << O() << ", P=" << P() << ']';
}                  // Pisanje.
};
#endif

// trougao.h
// Definicija klase trouglova (Trougao).
#ifndef _trougao_h_
#define _trougao_h_
#include "figura.h"
#include <cmath>
class Trougao : public Figura {
  Real a, b, c;                                   // Stranice.
public:                                           // Konstruktori:
  explicit Trougao(Real aa=1, const Tacka& tt=ORG)   // jednakostranicni
    : Figura(tt) { a = b = c = aa; }
  Trougao(Real aa, Real bb, const Tacka& tt=ORG)     // jednakokraki
    : Figura(tt) { a = aa; b = c = bb; }
  Trougao(Real aa, Real bb, Real cc, const Tacka& tt=ORG) // opsti
    : Figura(tt) { a = aa; b = bb; c = cc; }
  Trougao* kopija() const                         // Stvaranje kopije.
    { return new Trougao(*this); }
  Real O() const { return a + b + c; }            // Obim.
  Real P() const{                         // Povrsina.
  Real s = (a + b + c) / 2;
  return sqrt(s * (s-a) * (s-b) * (s-c));
}                                 // Povrsina.
private:
  void citaj(istream& ut){ Figura::citaj(ut); ut >> a >> b >> c; }                        // Citanje.
  void pisi (ostream& it) const{          // Pisanje.
  it << "trougao [";
  Figura::pisi(it);
  it << ", a=" << a << ", b=" << b   << ", c=" << c
     << ", O=" << O() << ", P=" << P() << ']';
}                  // Pisanje.
};
#endif

// glavni program
// Program za ispitivanje klasa za geometrijske figure.
#include "krug.h"
#include "kvadrat.h"
#include "trougao.h"
#include <iostream>
using namespace std;
int main () {
  // Element liste figura.
  struct Elem {
    Figura* fig; Elem* sled;
    Elem (Figura* ff, Elem* ss=0) { fig = ff; sled = ss; }
    ~Elem () { delete fig; }
  };
  Elem *prvi = 0, *posl = 0;
  // Stvaranje liste figura citajuci s glavnog ulaza.
  for (bool dalje=true; dalje; ) {
    Figura* pf;
    char vrsta;
    cout<<"vrsta figure: o - krug, k - kvadrat, t - trougao"<<endl;
    cout<<"najpre se unosi tacka figure, a zatim njeni parametri!"<<endl; cin >> vrsta;
    switch (vrsta) {
      case 'o': pf = new Krug;    break;
      case 'k': pf = new Kvadrat; break;
      case 't': pf = new Trougao; break;
      default: dalje = false;
    }

    if (dalje) {
      cin >> *pf;
      Elem* novi = new Elem (pf);
      posl = (!prvi ? prvi : posl->sled) = novi;
    }
  }
  // Prikazivanje sadrzaja liste na glavnom izlazu.
  for (Elem* tek=prvi; tek; tek=tek->sled) cout << *tek->fig << endl;
  // Citanje pomeraja za pomeranje figura.
  Real dx, dy;
  cout<<"pomeraj figura po x i y osi"<<endl;cin >> dx >> dy;
               cout << "\ndx, dy= " << dx << ", " << dy << "\n\n";
  // Stvaranje kopije liste uz pomeranje figura.
  Elem *poc = 0, *kraj = 0;
  for (Elem* tek=prvi; tek; tek=tek->sled) {
    Elem* novi = new Elem (tek->fig->kopija());
    novi->fig->pomeri(dx,dy);
    kraj = (!poc ? poc : kraj->sled) = novi;
  }
  // Unistavanje prve liste.
  while (prvi) { Elem* stari=prvi; prvi=prvi->sled; delete stari; }
  posl = 0;
  // Prikazivanje sadrzaja kopirane liste na glavnom izlazu.
  for (Elem* tek=poc; tek; tek=tek->sled) cout << *tek->fig << endl;
}

Оставите одговор

Попуните детаље испод или притисните на иконицу да бисте се пријавили:

WordPress.com лого

Коментаришет користећи свој WordPress.com налог. Одјавите се /  Промени )

Google photo

Коментаришет користећи свој Google налог. Одјавите се /  Промени )

Слика на Твитеру

Коментаришет користећи свој Twitter налог. Одјавите се /  Промени )

Фејсбукова фотографија

Коментаришет користећи свој Facebook налог. Одјавите се /  Промени )

Повезивање са %s