logo

Čistě virtuální funkce a abstraktní třídy v C++

Někdy nelze implementaci všech funkcí poskytnout v základní třídě, protože neznáme implementaci. Taková třída se nazývá an abstraktní třída .Například nechť je Shape základní třídou. Nemůžeme poskytnout implementaci funkce draw() v Shape, ale víme, že každá odvozená třída musí mít implementaci draw(). Podobně třída Animal nemá implementaci move() (za předpokladu, že se všechna zvířata pohybují), ale všechna zvířata musí vědět, jak se pohybovat. Nemůžeme vytvářet objekty abstraktních tříd.

A čistě virtuální funkce (nebo abstraktní funkce) v C++ je virtuální funkce, pro kterou můžeme mít implementaci, ale musíme tuto funkci přepsat v odvozené třídě, jinak se odvozená třída také stane abstraktní třídou. Čistá virtuální funkce je deklarována přiřazením 0 v deklaraci.



Příklad čistě virtuálních funkcí

C++






// An abstract class> class> Test {> >// Data members of class> public>:> >// Pure Virtual Function> >virtual> void> show() = 0;> >/* Other members */> };>



>

>

Kompletní příklad

Čistá virtuální funkce je implementována třídami, které jsou odvozeny z abstraktní třídy.

C++




// 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ýstup

fun() called>

Několik zajímavých faktů

1. Třída je abstraktní, pokud má alespoň jednu čistě virtuální funkci.

Příklad

java tostring

V níže uvedeném kódu C++ je Test abstraktní třída, protože má čistě virtuální funkci 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ýstup

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 mít ukazatele a odkazy typu abstraktní třídy.

Například následující program funguje dobře.

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ýstup

In Derived>

3. Pokud v odvozené třídě nepřepíšeme čistou virtuální funkci, stane se z odvozené třídy také abstraktní třída.

Následující příklad ukazuje totéž.

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ýstup

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í třída může mít konstruktory.

Například následující program se zkompiluje a běží v pořádku.

C++

fizzbuzz java




// 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;> }>

>

>

Výstup

Constructor of base called x = 4, y = 5 Constructor of base called x = 6, y = 7>

5. Abstraktní třídu v C++ lze také definovat pomocí klíčového slova struct.

Příklad

struct shapeClass { virtual void Draw()=0; }>

Srovnání s Javou

V Javě lze třídu učinit abstraktní pomocí abstraktního klíčového slova. Podobně lze funkci vytvořit čistě virtuální nebo abstraktní pomocí abstraktního klíčového slova. Vidět Abstraktní třídy v Javě Více podrobností.

Rozhraní vs abstraktní třídy

Rozhraní nemá implementaci žádné ze svých metod, lze jej považovat za soubor deklarací metod. V C++ lze rozhraní simulovat tak, že všechny metody budou čistě virtuální. V Javě je pro rozhraní samostatné klíčové slovo.

Rozhraní si můžeme představit jako hlavičkové soubory v C++, stejně jako v hlavičkových souborech poskytujeme pouze tělo třídy, která jej bude implementovat. Podobně v Javě v rozhraní poskytujeme pouze tělo třídy a napíšeme skutečný kód v jakékoli třídě, která jej implementuje.