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ă.