Niekedy nie je možné poskytnúť implementáciu všetkých funkcií v základnej triede, pretože nepoznáme implementáciu. Takáto trieda sa nazýva an abstraktná trieda .Napríklad nech je Shape základnou triedou. Nemôžeme poskytnúť implementáciu funkcie draw() v Shape, ale vieme, že každá odvodená trieda musí mať implementáciu draw(). Podobne trieda Animal nemá implementáciu move() (za predpokladu, že sa všetky zvieratá pohybujú), ale všetky zvieratá musia vedieť, ako sa pohybovať. Nemôžeme vytvárať objekty abstraktných tried.
A čistá virtuálna funkcia (alebo abstraktná funkcia) v C++ je virtuálna funkcia, pre ktorú môžeme mať implementáciu, ale musíme túto funkciu prepísať v odvodenej triede, inak sa odvodená trieda tiež stane abstraktnou triedou. Čistá virtuálna funkcia je deklarovaná priradením 0 v deklarácii.
Príklad čistých virtuálnych funkcií
C++
// An abstract class> class> Test {> >// Data members of class> public>:> >// Pure Virtual Function> >virtual> void> show() = 0;> >/* Other members */> };> |
>
>
Kompletný príklad
Čistá virtuálna funkcia je implementovaná triedami, ktoré sú odvodené od abstraktnej triedy.
C++
reťazcový formát java
// C++ Program to illustrate the abstract class and virtual> // functions> #include> using> namespace> std;> class> Base {> >// private member variable> >int> x;> public>:> >// pure virtual function> >virtual> void> fun() = 0;> >// getter function to access x> >int> getX() {>return> x; }> };> // This class inherits from Base and implements fun()> class> Derived :>public> Base {> >// private member variable> >int> y;> public>:> >// implementation of the pure virtual function> >void> fun() { cout <<>'fun() called'>; }> };> int> main(>void>)> {> >// creating an object of Derived class> >Derived d;> >// calling the fun() function of Derived class> >d.fun();> >return> 0;> }> |
>
>Výkon
fun() called>
Niektoré zaujímavé fakty
1. Trieda je abstraktná, ak má aspoň jednu čisto virtuálnu funkciu.
Príklad
V nižšie uvedenom kóde C++ je Test abstraktná trieda, pretože má čisto virtuálnu funkciu show().
C++
// C++ program to illustrate the abstract class with pure> // virtual functions> #include> using> namespace> std;> class> Test {> >// private member variable> >int> x;> public>:> >// pure virtual function> >virtual> void> show() = 0;> >// getter function to access x> >int> getX() {>return> x; }> };> int> main(>void>)> {> >// Error: Cannot instantiate an abstract class> >Test t;> >return> 0;> }> |
>
>
Výkon
Compiler Error: cannot declare variable 't' to be of abstract type 'Test' because the following virtual functions are pure within 'Test': note: virtual void Test::show()>
2. Môžeme mať ukazovatele a odkazy typu abstraktnej triedy.
Napríklad nasledujúci program funguje dobre.
čísla v abecede
C++
// C++ program that demonstrate that> // we can have pointers and references> // of abstract class type.> #include> using> namespace> std;> class> Base {> public>:> >// pure virtual function> >virtual> void> show() = 0;> };> class> Derived :>public> Base {> public>:> >// implementation of the pure virtual function> >void> show() { cout <<>'In Derived
'>; }> };> int> main(>void>)> {> >// creating a pointer of type> >// Base pointing to an object> >// of type Derived> >Base* bp =>new> Derived();> >// calling the show() function using the> >// pointer> >bp->show();> >return> 0;> }> |
>
>Výkon
vypnutie režimu vývojára v systéme Android
In Derived>
3. Ak v odvodenej triede neprepíšeme čistú virtuálnu funkciu, potom sa aj odvodená trieda stane abstraktnou triedou.
Nasledujúci príklad ukazuje to isté.
C++
// C++ program to demonstrate that if we do not override> // the pure virtual function in the derived class, then> // the derived class also becomes an abstract class> #include> using> namespace> std;> class> Base {> public>:> >// pure virtual function> >virtual> void> show() = 0;> };> class> Derived :>public> Base {> };> int> main(>void>)> {> >// creating an object of Derived class> >Derived d;> >return> 0;> }> |
>
>
Výkon
Compiler Error: cannot declare variable 'd' to be of abstract type 'Derived' because the following virtual functions are pure within 'Derived': virtual void Base::show()>
4. Abstraktná trieda môže mať konštruktory.
Napríklad nasledujúci program sa skompiluje a funguje správne.
C++
// C++ program to demonstrate that> // an abstract class can have constructors.> #include> using> namespace> std;> // An abstract class with constructor> class> Base {> protected>:> >// protected member variable> >int> x;> public>:> >// pure virtual function> >virtual> void> fun() = 0;> >// constructor of Base class> >Base(>int> i)> >{> >x = i;> >cout <<>'Constructor of base called
'>;> >}> };> class> Derived :>public> Base {> >// private member variable> >int> y;> public>:> >// calling the constructor of Base class> >Derived(>int> i,>int> j)> >: Base(i)> >{> >y = j;> >}> >// implementation of pure virtual function> >void> fun()> >{> >cout <<>'x = '> << x <<>', y = '> << y <<>'
'>;> >}> };> int> main(>void>)> {> >// creating an object of Derived class> >Derived d(4, 5);> >// calling the fun() function of Derived class> >d.fun();> >// creating an object of Derived class using> >// a pointer of the Base class> >Base* ptr =>new> Derived(6, 7);> >// calling the fun() function using the> >// pointer> >ptr->fun();> >return> 0;> }> |
>
nfa na dfa
>Výkon
Constructor of base called x = 4, y = 5 Constructor of base called x = 6, y = 7>
5. Abstraktnú triedu v C++ je možné definovať aj pomocou kľúčového slova struct.
Príklad
struct shapeClass { virtual void Draw()=0; }> Porovnanie s Javou
V jazyku Java môže byť trieda abstraktná pomocou abstraktného kľúčového slova. Podobne môže byť funkcia pomocou abstraktného kľúčového slova čistá virtuálna alebo abstraktná. Pozri Abstraktné triedy v Jave pre viac detailov.
Rozhranie vs abstraktné triedy
Rozhranie nemá implementáciu žiadnej zo svojich metód, možno ho považovať za súbor deklarácií metód. V C++ je možné simulovať rozhranie tak, že všetky metódy budú čisto virtuálne. V jazyku Java existuje samostatné kľúčové slovo pre rozhranie.
Rozhranie si môžeme predstaviť ako hlavičkové súbory v C++, podobne ako v hlavičkových súboroch poskytujeme iba telo triedy, ktorá ho bude implementovať. Podobne v jazyku Java v rozhraní poskytujeme iba telo triedy a napíšeme skutočný kód v akejkoľvek triede, ktorá ho implementuje.