Funcții virtuale pure și clase abstracte în C++

Uneori, implementarea tuturor funcțiilor nu poate fi furnizată într-o clasă de bază, deoarece nu cunoaștem implementarea. O astfel de clasă se numește an clasa abstractă .De exemplu, să fie Shape o clasă de bază. Nu putem oferi implementarea funcției draw() în Shape, dar știm că fiecare clasă derivată trebuie să aibă o implementare a draw(). În mod similar, o clasă Animal nu are implementarea move() (presupunând că toate animalele se mișcă), dar toate animalele trebuie să știe cum să se miște. Nu putem crea obiecte din clase abstracte.

A funcție virtuală pură (sau funcție abstractă) în C++ este o funcție virtuală pentru care putem avea o implementare, Dar trebuie să suprascriem acea funcție în clasa derivată, altfel, clasa derivată va deveni și o clasă abstractă. O funcție virtuală pură este declarată prin atribuirea lui 0 în declarație.

Exemplu de funcții virtuale pure

C++




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

Exemplu complet

O funcție virtuală pură este implementată de clase care sunt derivate dintr-o clasă Abstract.

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

Ieșire

fun() called 

Câteva fapte interesante

1. O clasă este abstractă dacă are cel puțin o funcție virtuală pură.

Exemplu

În codul C++ de mai jos, Testul este o clasă abstractă, deoarece are o funcție virtuală pură 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;> }>

Ieșire

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. Putem avea pointeri și referințe de tip de clasă abstractă.

De exemplu, următorul program funcționează bine.

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->arată();> > return> 0;> }>

Ieșire

In Derived 

3. Dacă nu suprascriem funcția virtuală pură în clasa derivată, atunci clasa derivată devine și ea o clasă abstractă.

Următorul exemplu demonstrează același lucru.

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

Ieșire

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. O clasă abstractă poate avea constructori.

De exemplu, următorul program compilează și rulează bine.

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->distracție();> > return> 0;> }>

Ieșire

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

5. O clasă abstractă în C++ poate fi definită și folosind cuvântul cheie struct.

Exemplu

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

Comparație cu Java

În Java, o clasă poate fi făcută abstractă folosind un cuvânt cheie abstract. În mod similar, o funcție poate fi făcută pur virtuală sau abstractă folosind un cuvânt cheie abstract. Vedea Clase abstracte în Java pentru mai multe detalii.

Interfață vs Clase abstracte

O interfață nu are o implementare a vreuneia dintre metodele sale, ea poate fi considerată ca o colecție de declarații de metodă. În C++, o interfață poate fi simulată făcând toate metodele pur virtuale. În Java, există un cuvânt cheie separat pentru interfață.

Ne putem gândi la Interfață ca fișiere antet în C++, ca și în fișierele antet, furnizăm doar corpul clasei care o va implementa. În mod similar, în Java în Interfață, oferim doar corpul clasei și scriem codul real în orice clasă îl implementează.