Metody wirtualne

  • Published on
    22-Jan-2016

  • View
    39

  • Download
    0

Embed Size (px)

DESCRIPTION

Metody wirtualne. Dlaczego metody wirtualne?. W C++ dla wskanikw i referencji dozwolona jest konwersja potomna bazowa . przez taki wskanik lub referencj mona odwoywa si jedynie do danych zadeklarowanych w klasie bazowej, oraz jedynie do metod klasy bazowej - PowerPoint PPT Presentation

Transcript

  • Metody wirtualne

  • Dlaczego metody wirtualne?W C++ dla wskanikw i referencji dozwolona jest konwersja potomna bazowa.przez taki wskanik lub referencj mona odwoywa si jedynie do danych zadeklarowanych w klasie bazowej, oraz jedynie do metod klasy bazowej na podstawie klasy wskanika/referencji kompilator zdecyduje o wywoaniu metody kl. bazowej nazwet jeeli obiekt jest klasy potomnej.

  • class punkt{ int x,y;

    public: void pokaz(); //rysuje punkt void ukryj();};

    class okrag: public punkt{ int r;

    public: void pokaz(); //rysuje punkt void ukryj();};

    okrag o;punkt *rp=&o;rp->pokaz(); //punkt::pokaz

  • Dlaczego metody wirtualne?okrag o;punkt *rp=&o;rp->pokaz(); // niech wywoa si okrag::pokaz

    jak to zrealizowa?

  • class punkt{ int x,y;protected: char klasa;public: void pokaz(); //rysuje punkt

    punkt(int x, int y) :x(x), y(y), { klasa=p; }};

    Rozwizanie niedoskonaeWadliweclass okrag: public punkt{ int r;public: void pokaz(); //rysuje punkt okrag(int x, int y, int r) :punkt(x,y), r(r) { klasa=o; }};

    okrag o;punkt *rp=&o;if (rp->klasa==p) rp->punkt::pokaz(); else rp->okrag::pokaz();

  • Metody wirtualneJeeli zadeklarujemy metod jako wirtualn to kompilator uzupeni obiekty o pole determinujce klas obiektu i przy wywoywaniu wybranych przez nas metod wywoa metod z waciwej klasy.

    void virtual punkt::ukryj();

    Metod (albo operator) wystarczy raz zadeklarowa jako wirtualny, w klasach pochodnych moemy, ale nie musimy uywa sowa kluczowego virtual.

  • class punkt{ int x,y;

    public: void virtual pokaz(); void virtual ukryj();};

    class okrag: public punkt{ int r;

    public: void pokaz(); // virtual void ukryj(); // virtual};Metody wirtualne

  • Metody wirtualne - dziaanieDo pierwszej klasy w ktrej w hierarchii klas pojawi si metoda wirtualna dodane zostanie dodatkowe niejawne pole adres tablicy metod wirtualnych. zwikszy si rozmiar obiektw tej klasy.

    Dla obiektu, ktrego klasy nie mona jednoznacznie okreli na etapie kompilacji, odwoania do metody, bd metod zadeklarowanych jako wirtualne bd si odbyway porednio poprzez tablic metod wirtualnych bdzie to dziaao wolniej ni odwoanie bezporednie, metody wirtualne nie bd rozwijane inline,bdzie to dziaao szybciej, ni gdybymy tak sztuczk robili rcznie,kompilator nie pomyli si (czowiek wiadomo).

  • Metody wirtualne - dziaanieOdwoania przez wskanik i referencje bd porednie

    Odwoania przez kwalifikacj obiektem bd bezporednie a wic szybsze, metody (nawet zadeklarowane z virtual) mog by rozwijane inline.

    Uwaga: metody klasy mog zosta odziedziczone i aktywowane na rzecz obiektu klasy pochodnej, a wic odwoania do wirtualnych metod danej klasy z innych metod tej klasy bd te porednie!

  • class punkt{ int x,y;

    public: void virtual pokaz(); void virtual ukryj(); void przesun(int dx, int dy) { ukryj(); // wirtualna w punkt x+=dx; y+=dy; pokaz(); // wirtualna w punkt }};

    class okrag: public punkt{ int r;

    public: void pokaz(); void ukryj();};

    okrag o;punkt *rp=&o;rp->pokaz(); //okrag::pokaz

    rp->przesun(); //punkt::przesun wywoa //okrag::pokaz i okrag::ukyj !!!

  • Klasa polimorficznaklasa polimorficzna to taka w ktrej wystpuje przynajmniej jedna metoda wirtualna

    Przykad korzyci z polimorfizmu:deklarujemy list przechowujc wskaniki do punktw (klasa polimorficzna) - na licie umieszcza punkty okrgi i inne figury.przez wskaniki moemy pokaza wszystkie figury (wywoujc metod wirtualn pokaz() porednio), moemy te przesuwa figury wyw. si niewirtualna metoda przesu, ona wywoa waciwe, bo wirtualne pokaz i ukryj.

  • Wczesne i pne wizanieWczesne wizanie:gdy metoda nie jest wirtualna lub jest wirtualna ale mona okreli z ktrej klasy ma pochodzi to nazwa metody jest kojarzona z jej kodem (wywoanie metody albo nawet rozwinicie inline) ju na etapie kompilacji/linkowania.Pne wizanie decyzja co do wyboru klasy z zakresu ktrej metod wykona, zostaje podjta podczas biegu programu.

  • Wczesne i pne wizanieMetody nie-wirtualne zawsze wczesne wizanie.

    Zadeklarowanie metody jako wirtualnej nie wyklucza jej wczesnego wizania, nastpi ono, gdy:jawnie (operatorem zakresu) podamy o ktr klas nam chodzi, wywoamy metod bezporednio na rzecz obiektu (nie przez wskanik lub referencj).

  • Metody wirtualnezaleta: ogromna atwo rozbudowy programu, Piszc kod moemy wykorzystywa metody ktrych jeszcze nie napisano !Nie musimy powiela takiego samego kodu w metodach rnych klas (vide przesun()). Nie grozi nam uzupenienie ju gotowego kodu o nowe bdy.

  • Konstruktory i destruktoryKonstruktor nie moe by wirtualny (dlaczego?)

    Destruktor moe i czasami powinien by virtual (dlaczego?)Uwaga: Gdy w jakiej klasie zadeklarujemy destruktor jako wirtualny, to w klasach pochodnych destruktory te bd wirtualne (mimo e ich nazwy w klasach pochodnych bd inne).

  • Static i virtualMetoda statyczna nie moe by wirtualna (dlaczego?).

  • Dziedziczenie metod wirtualnychmeoda wirtualna moe zosta odziedziczona przez klas pochodn moe zosta przedefiniowana, w jej ciele moemy wywoa metod wirtualn klasy bazowej.

    np.:

    void okrag::pokaz() { punkt::pokaz(); // narysuj rodek okrgu //narysuj okrg }

  • Przecianie a wirtualno wirtualno dotyczy tylko tej metody/operatora ktra zostaa w danej klasie lub przodku zadeklarowana jako virtual, inne metody (o innych parametrach) s zwykymi metodami/operatorami.

    np. metoda nie wirtualna:

    void punkt::pokaz(char * opis){...};

  • Zaprzyjanianie a wirtualnoWirtualno jest niezalena od zaprzyjaniania. Zaprzyjanianie nie jest przechodnie, Zaprzyjanianie dotyczy tylko tej metody (klasa::metoda) ktra zostaa zaprzyjaniona,Metoda przedefiniowana w klasie pochodnej, wirtualna czy nie, nie bdzie automatycznie zaprzyjaniona.

  • Widoczno metod wirtualnychWidoczno jest rozstrzygana na etapie kompilacjizatem decyduje typ wskanika/referencji.

    np., przyjmijmy, e wszystkie skadowe klasy okrg sa prywatne:

    okrag o;punkt *rp=&o;rp->pokaz(); // OK dlaczego?

  • Klasa abstrakcyjnaKlasa abstrakcyjna, to klasa, ktra nie zawiera adnych obiektw.

    Klasa abstrakcyjna suy do definiowania interfejsu/cech wsplnych rodziny innych klas (jej potomkw)np. klasa abstrakcyjna figura liczba

    Dziedziczenie klas abstrakcyjnych

  • Metoda czysto wirtualnaW C++ klasa abstrakcyjna to taka, ktra zawiera przynajmniej jedn metod czysto wirtualn tj. tak ktra jest wirtualna, i nie ma zdefiniowanego ciaa.

    void virtual figura::rysuj()=0;

  • RTTIPoniewa wskanikowi na przodka mona przypisa adres potomka to typ wskanika nie determinuje klasy do ktrej naley obiekt wskazywany. Czasami w trakcie dziaania programu pojawia si potrzeba sprawdzenia do jakiej klasy dany obiekt naley. Jeeli wskanik bd referencja dotyczy klasy polimorficznej to obiekt zawiera pole umoliwiajce identyfikacj klasy (wskanik do tablicy metod wirtualnych), na jego podstawie mechanizm RTTI pozwala sprawdza typy w trakcie biegu programu. Jeeli wskanik, bd referencja dotyczy typu podstawowego bd klasy nie-polimorficznej to typ okrelany jest na podstawie typu wskanika/referencji a nie rzeczywistego obiektu/zmiennej bo nie ma danych by to zrobi inaczej.

  • RTTIRTTI RunTime Type Information

    operator typeid

    type_info typeid(arg)

    arg: typ, klasa, zmienna bd obiekt

  • RTTIclass type_info { // tu prywatny konstruktor kopiujcy i operator przypisania // nie mona z zewntrz tworzy kopii obiektw tej klasypublic: virtual ~type_info(); bool operator==(const type_info& rhs) const; bool operator!=(const type_info& rhs) const; bool before(const type_info& rhs) const; const char* name() const;};

  • RTTIclass A { virtual void a(){}; };class B:public A {};class C:public B {};

    A a, *pa;C c;pa=&c;

    typeid(C)==typeid(pa)// 0 typeid(a)==typeid(*pa)// 0 typeid(c)==typeid(*pa) // 1 typeid(B).name() // B typeid(pa).name() // A * typeid(*pa).name() // C typeid(A).before(typeid(*pa)) // 1 typeid(B).before(typeid(*pa)) // 1 typeid(C).before(typeid(*pa)) // 0 typeid(C).before(typeid(a)) // 0

  • *_castoperatory rzutowania dla zastpienia rzutowania w stylu jzyka C

    static_cast < type-id > ( wyraenie ) dynamic_cast < type-id > ( wyraenie ) reinterpret_cast < type-id > ( wyraenie ) const_cast < type-id > ( wyraenie )

    to 4 operatory i 4 sowa kluczowe C++zaprojektowane by umoliwi wiksz kontrol na poziomie kompilacji i wykonania kodu nad (podatnymi na bdy) rzutowaniamipozwalaj wyrazi intencj programisty

  • static_caststatic_cast < type-id > ( wyraenie )

    rzutownie oparte na typach znanych podczas kompilacjipodobnie niebezpiczne jak rzutowanie C: (type-id ) wyraenie uywa ostoniedziaa szybkonie dopuszcza si modyfikacji kwalifikacji const i volatile wyraenia

  • static_caststatic_cast < type-id > ( wyraenie )

    class A {};

    class B:public A{int method();};

    int fun(A * pa){static_cast(pa) -> method()// miejmy nadziej, e pa wskazuje na B }

  • dynamic_castdynamic_cast < type-id > ( wyraenie )

    rzutowanie oparte o RTTI, uywane ze wskanikami i referencjamidla wskanikw zwraca NULL, jeli type-id nie jest ani typu wyraenia ani jego rodzicadla referencji w ww. przypadku zgaszany jest wyjtekbezpieczne, mniej szybkienie dopuszcza si modyfikacji kwalifikacji const i volatile wyraenia

  • dynamic_castdynamic_cast < type-id > ( wyraenie )

    class A {};

    class B:public A{};

    int fun(){A *pa, *aptr=new A;B *pb, *bptr=new B;...pa=dynamic_cast(bptr); // OKpb=dyn