logo

Czyste funkcje wirtualne i klasy abstrakcyjne w C++

Czasami nie można zapewnić implementacji wszystkich funkcji w klasie bazowej, ponieważ nie znamy implementacji. Taka klasa nazywa się an klasa abstrakcyjna .Na przykład niech Shape będzie klasą bazową. Nie możemy zapewnić implementacji funkcji Draw() w Shape, ale wiemy, że każda klasa pochodna musi mieć implementację funkcji Draw(). Podobnie klasa Animal nie ma implementacji metody move() (zakładając, że wszystkie zwierzęta się poruszają), ale wszystkie zwierzęta muszą wiedzieć, jak się poruszać. Nie możemy tworzyć obiektów klas abstrakcyjnych.

A czysta funkcja wirtualna (lub funkcja abstrakcyjna) w C++ jest funkcją wirtualną, dla której możemy mieć implementację, ale musimy zastąpić tę funkcję w klasie pochodnej, w przeciwnym razie klasa pochodna również stanie się klasą abstrakcyjną. Czystą funkcję wirtualną deklaruje się poprzez przypisanie w deklaracji wartości 0.

Przykład czystych funkcji wirtualnych

C++






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

>

>

Kompletny przykład

Czysta funkcja wirtualna jest implementowana przez klasy wywodzące się z klasy abstrakcyjnej.

C++

wiek Pete'a Davidsona




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

>

>

Wyjście

fun() called>

Kilka interesujących faktów

1. Klasa jest abstrakcyjna, jeśli ma co najmniej jedną czysto wirtualną funkcję.

Przykład

W poniższym kodzie C++ Test jest klasą abstrakcyjną, ponieważ zawiera czystą funkcję wirtualną 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;> }>

>

>

Wyjście

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. Możemy mieć wskaźniki i referencje typu klasy abstrakcyjnej.

Na przykład następujący program działa dobrze.

jak sprawdzić rozmiar mojego monitora

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->pokaż();> >return> 0;> }>

>

>

Wyjście

porównać do ciągów znaków w Javie
In Derived>

3. Jeżeli w klasie pochodnej nie nadpiszemy czystej funkcji wirtualnej, to klasa pochodna również stanie się klasą abstrakcyjną.

Poniższy przykład pokazuje to samo.

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

>

>

Wyjście

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. Klasa abstrakcyjna może posiadać konstruktory.

Na przykład następujący program kompiluje się i działa poprawnie.

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

>

fizzbuzz Java
>

Wyjście

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

5. Klasę abstrakcyjną w C++ można również zdefiniować za pomocą słowa kluczowego struct.

Przykład

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

Porównanie z Javą

W Javie klasę można uczynić abstrakcyjną za pomocą słowa kluczowego abstrakcyjnego. Podobnie funkcję można przekształcić w czysto wirtualną lub abstrakcyjną, używając abstrakcyjnego słowa kluczowego. Widzieć Klasy abstrakcyjne w Javie po więcej szczegółów.

Interfejs a klasy abstrakcyjne

Interfejs nie posiada implementacji żadnej ze swoich metod, można go uznać za zbiór deklaracji metod. W C++ interfejs można symulować, czyniąc wszystkie metody czysto wirtualnymi. W Javie istnieje osobne słowo kluczowe określające interfejs.

Możemy myśleć o interfejsie jako o plikach nagłówkowych w C++, podobnie jak w plikach nagłówkowych udostępniamy tylko treść klasy, która będzie go implementować. Podobnie w Javie w interfejsie podajemy tylko treść klasy i piszemy rzeczywisty kod w dowolnej klasie, która go implementuje.