Co to jest polimorfizm w C ++?
W C ++ polimorfizm powoduje, że funkcja składowa zachowuje się inaczej w zależności od obiektu, który ją wywołuje / wywołuje. Polimorfizm to greckie słowo, które oznacza mieć wiele form. Występuje, gdy masz hierarchię klas powiązanych przez dziedziczenie.
Na przykład załóżmy, że mamy funkcję makeSound (). Gdy kot wywoła tę funkcję, wyda dźwięk miauczenia. Gdy krowa wywoła tę samą funkcję, wyda dźwięk roju.
Chociaż mamy jedną funkcję, zachowuje się ona inaczej w różnych okolicznościach. Funkcja ma wiele form; stąd osiągnęliśmy polimorfizm.
W tym samouczku C ++ nauczysz się:
- Co to jest polimorfizm?
- Rodzaje polimorfizmu
- Polimorfizm czasu kompilacji
- Przeciążanie funkcji
- Przeciążanie operatorów
- Polimorfizm w czasie wykonywania
- Funkcja zastępująca
- Funkcja wirtualna C ++
- Polimorfizm w czasie kompilacji vs. Polimorfizm w czasie wykonywania
Rodzaje polimorfizmu
C ++ obsługuje dwa typy polimorfizmu:
- Polimorfizm w czasie kompilacji i
- Polimorfizm w czasie wykonywania.
Polimorfizm czasu kompilacji
Możesz wywołać przeciążone funkcje, dopasowując liczbę i typ argumentów. Informacje są obecne w czasie kompilacji. Oznacza to, że kompilator C ++ wybierze odpowiednią funkcję w czasie kompilacji.
Polimorfizm w czasie kompilacji uzyskuje się poprzez przeciążanie funkcji i przeciążanie operatorów.
Przeciążanie funkcji
Przeciążanie funkcji występuje, gdy mamy wiele funkcji o podobnych nazwach, ale różnych argumentach. Argumenty mogą się różnić pod względem liczby lub typu.
Przykład 1:
#includeusing namespace std;void test(int i) {cout << " The int is " << i << endl;}void test(double f) {cout << " The float is " << f << endl;}void test(char const *ch) {cout << " The char* is " << ch << endl;}int main() {test(5);test(5.5);test("five");return 0;}
Wynik:
Oto zrzut ekranu kodu:
Objaśnienie kodu:
- Dołącz plik nagłówkowy iostream do naszego kodu. Będziemy mogli korzystać z jego funkcji.
- Uwzględnij przestrzeń nazw std w naszym kodzie. Będziemy mogli korzystać z jego klas bez wywoływania go.
- Utwórz funkcję o nazwie test, która przyjmuje parametr w postaci liczby całkowitej i. {Oznacza początek treści testu funkcji.
- Instrukcja do wykonania, jeśli powyższy test funkcji jest wywoływany / wywoływany.
- Koniec treści powyższego testu funkcjonalnego.
- Utwórz funkcję o nazwie test, która przyjmuje parametr zmiennoprzecinkowy f. {Oznacza początek treści testu funkcji.
- Instrukcja do wykonania, jeśli powyższy test funkcji jest wywoływany / wywoływany.
- Koniec treści powyższego testu funkcjonalnego.
- Utwórz funkcję o nazwie test, która przyjmuje parametr znakowy ch. {Oznacza początek treści testu funkcji.
- Instrukcja do wykonania, jeśli powyższy test funkcji jest wywoływany / wywoływany.
- Koniec treści powyższego testu funkcjonalnego.
- Wywołaj funkcję main (). {Oznacza początek treści funkcji.
- Wywołaj funkcję test i przekaż do niej 5 jako wartość argumentu. Powoduje to wywołanie funkcji testowej, która przyjmuje argument będący liczbą całkowitą, czyli pierwszą funkcję testową.
- Wywołaj funkcję test i przekaż do niej 5.5 jako wartość argumentu. Spowoduje to wywołanie funkcji testowej, która przyjmuje argument zmiennoprzecinkowy, czyli drugą funkcję testową.
- Wywołaj funkcję test i przekazując do niej pięć jako wartość argumentu. Spowoduje to wywołanie funkcji testowej, która przyjmuje argument znakowy, czyli trzecią funkcję testową.
- Program musi zwrócić wartość, jeśli działa pomyślnie.
- Koniec treści funkcji main ().
Mamy trzy funkcje o tej samej nazwie, ale z różnymi typami argumentów. Osiągnęliśmy polimorfizm.
Przeciążanie operatorów
W Przeciążaniu operatorów definiujemy nowe znaczenie dla operatora C ++. Zmienia również sposób działania operatora. Na przykład możemy zdefiniować operator + do łączenia dwóch ciągów. Znamy to jako operator dodawania do dodawania wartości liczbowych. Po naszej definicji, umieszczona między liczbami całkowitymi, doda je. Po umieszczeniu między łańcuchami połączy je.
Przykład 2:
#includeusing namespace std;class ComplexNum {private:int real, over;public:ComplexNum(int rl = 0, int ov = 0) {real = rl;over = ov;}ComplexNum operator + (ComplexNum const &obj) {ComplexNum result;result.real = real + obj.real;result.over = over + obj.over;return result;}void print() {cout << real << " + i" << over << endl;}};int main(){ComplexNum c1(10, 2), c2(3, 7);ComplexNum c3 = c1+c2;c3.print();}
Wynik:
Oto zrzut ekranu kodu:
Objaśnienie kodu:
- Dołącz plik nagłówkowy iostream do naszego programu, aby móc korzystać z jego funkcji.
- Dołącz przestrzeń nazw std do naszego programu, aby używać jego klas bez wywoływania jej.
- Utwórz klasę o nazwie ComplexNum. {Oznacza początek treści klasy.
- Użyj modyfikatora dostępu prywatnego, aby oznaczyć zmienne jako prywatne, co oznacza, że można uzyskać do nich dostęp tylko z poziomu klasy.
- Zdefiniuj dwie zmienne całkowite, rzeczywistą i wyższą.
- Użyj modyfikatora dostępu publicznego, aby oznaczyć konstruktor jako publiczny, co oznacza, że będzie dostępny nawet spoza klasy.
- Utwórz konstruktor klasy i zainicjuj zmienne.
- Zainicjuj wartość zmiennej real.
- Zainicjuj wartość zmiennej powyżej.
- Koniec treści konstruktora.
- Musimy nadpisać znaczenie operatora +.
- Utwórz wynik typu danych typu ComplexNum.
- Użyj operatora + na liczbach zespolonych. Ta linia doda część rzeczywistą liczby do części rzeczywistej innej liczby.
- Użyj operatora + na liczbach zespolonych. Ta linia doda urojoną część liczby do urojonej części innej liczby.
- Program zwróci wartość wyniku zmiennej po pomyślnym wykonaniu.
- Koniec definicji nowego znaczenia operatora +, czyli przeciążenia.
- Wywołaj metodę print ().
- Wydrukuj nową liczbę zespoloną po dodaniu na konsoli.
- Koniec treści funkcji print ().
- Koniec treści klasy ComplexNum.
- Wywołaj funkcję main ().
- Przekaż wartości zarówno rzeczywistych, jak i złożonych części, które mają zostać dodane. Pierwsza część c1 zostanie dodana do pierwszej części c2, czyli 10 + 3. Druga część c1 zostanie dodana do drugiej części c, czyli 2 + 7.
- Wykonaj operację, używając przeciążonego operatora + i przechowując wynik w zmiennej c3.
- Wydrukuj wartość zmiennej c3 na konsoli.
- Koniec treści funkcji main ().
Polimorfizm w czasie wykonywania
Dzieje się tak, gdy metoda obiektu jest wywoływana / wywoływana w czasie wykonywania, a nie w czasie kompilacji. Polimorfizm w czasie wykonywania jest osiągany poprzez nadpisywanie funkcji. Funkcja, która ma zostać wywołana / wywołana, jest ustanawiana w czasie wykonywania.
Funkcja zastępująca
Zastępowanie funkcji występuje, gdy funkcja klasy bazowej otrzymuje nową definicję w klasie pochodnej. W tym czasie możemy powiedzieć, że funkcja podstawowa została nadpisana.
Na przykład:
#includeusing namespace std;class Mammal {public:void eat() {cout << "Mammals eat… ";}};class Cow: public Mammal {public:void eat() {cout << "Cows eat grass… ";}};int main(void) {Cow c = Cow();c.eat();return 0;}
Wynik:
Oto zrzut ekranu kodu:
Objaśnienie kodu:
- Zaimportuj plik nagłówkowy iostream do naszego programu, aby użyć jego funkcji.
- Dołącz przestrzeń nazw std do naszego programu, aby używać jego klas bez wywoływania jej.
- Utwórz klasę o nazwie Mammal. {Oznacza początek treści klasy.
- Użyj modyfikatora dostępu publicznego, aby ustawić funkcję, którą zamierzamy utworzyć, jako publicznie dostępną. Będzie dostępny spoza tej klasy.
- Utwórz funkcję publiczną o nazwie eat. {Oznacza początek ciała funkcji.
- Wyświetla instrukcję dodaną do funkcji cout, gdy wywoływana jest funkcja eat ().
- Koniec treści funkcji eat ().
- Koniec treści klasy Mammal.
- Utwórz klasę o nazwie Cow, która dziedziczy klasę Mammal. Cow to klasa pochodna, a Mammal to klasa bazowa. {Oznacza początek tej klasy.
- Użyj modyfikatora dostępu publicznego, aby oznaczyć funkcję, którą zamierzamy utworzyć, jako publicznie dostępną. Będzie dostępny spoza tej klasy.
- Zastąp funkcję eat () zdefiniowaną w klasie bazowej. {Oznacza początek ciała funkcji.
- Instrukcja do wydrukowania na konsoli, gdy ta funkcja jest wywoływana.
- Koniec treści funkcji eat ().
- Koniec ciała klasy Cow.
- Wywołaj funkcję main (). {Oznacza początek treści tej funkcji.
- Utwórz instancję klasy Cow i nadaj jej nazwę. C.
- Wywołaj funkcję eat () zdefiniowaną w klasie Cow.
- Program musi zwrócić wartość po pomyślnym zakończeniu.
- Koniec funkcji main ().
Funkcja wirtualna C ++
Funkcja wirtualna to kolejny sposób implementacji polimorfizmu czasu wykonywania w C ++. Jest to specjalna funkcja zdefiniowana w klasie bazowej i przedefiniowana w klasie pochodnej. Aby zadeklarować funkcję wirtualną, należy użyć słowa kluczowego virtual. Słowo kluczowe powinno poprzedzać deklarację funkcji w klasie bazowej.
Jeśli klasa funkcji wirtualnej jest dziedziczona, klasa wirtualna na nowo definiuje funkcję wirtualną zgodnie z jej potrzebami. Na przykład:
#includeusing namespace std;class ClassA {public:virtual void show() {cout << "The show() function in base class invoked… " << endl;}};class ClassB :public ClassA {public:void show() {cout << "The show() function in derived class invoked… ";}};int main() {ClassA* a;ClassB b;a = &b;a->show();}
Wynik:
Oto zrzut ekranu kodu:
Objaśnienie kodu:
- Dołącz plik nagłówkowy iostream do kodu, aby używać jego funkcji.
- Uwzględnij przestrzeń nazw std w naszym kodzie, aby używać jej klas bez wywoływania jej.
- Utwórz klasę o nazwie ClassA.
- Użyj modyfikatora dostępu publicznego, aby oznaczyć element członkowski klasy jako publicznie dostępny.
- Utwórz funkcję wirtualną o nazwie show (). Będzie to funkcja publiczna.
- Tekst do wydrukowania po wywołaniu metody show (). Endl to słowo kluczowe C ++, które oznacza linię końcową. Przenosi kursor myszy do następnej linii.
- Koniec treści funkcji wirtualnej show ().
- Koniec treści klasy ClassA.
- Utworzenie nowej klasy o nazwie ClassB, która dziedziczy klasę ClassA. ClassA staje się klasą bazową, podczas gdy ClassB staje się klasą pochodną.
- Użyj modyfikatora dostępu publicznego, aby oznaczyć element członkowski klasy jako publicznie dostępny.
- Przedefiniuj funkcję wirtualną show () pochodzącą z klasy bazowej.
- Tekst do wydrukowania na konsoli, gdy wywoływana jest funkcja show () zdefiniowana w klasie pochodnej.
- Koniec treści funkcji show ().
- Koniec treści klasy pochodnej, ClassB.
- Wywołaj funkcję main (). Logikę programu należy dodać w jego treści.
- Utwórz zmienną wskaźnikową o nazwie a. Wskazuje na klasę o nazwie ClassA.
- Utwórz wystąpienie klasy o nazwie ClassB. Instancja otrzyma nazwę b.
- Przypisz wartości przechowywane w adresie b w zmiennej a.
- Wywołaj funkcję show () zdefiniowaną w klasie pochodnej. Wdrożono późne wiązanie.
- Koniec treści funkcji main ().
Polimorfizm w czasie kompilacji vs. Polimorfizm w czasie wykonywania
Oto główne różnice między nimi:
Polimorfizm w czasie kompilacji | Polimorfizm w czasie wykonywania |
Nazywa się to również wczesnym wiązaniem lub polimorfizmem statycznym | Nazywa się to również późnym / dynamicznym wiązaniem lub dynamicznym polimorfizmem |
Metoda jest wywoływana / wywoływana w czasie kompilacji | Metoda jest wywoływana / wywoływana w czasie wykonywania |
Realizowane poprzez przeciążanie funkcji i przeciążanie operatorów | Realizowane za pomocą nadpisywania metod i funkcji wirtualnych |
Przykład, przeciążenie metody. Wiele metod może mieć podobne nazwy, ale różną liczbę lub typy argumentów | Przykład, przesłanianie metody. Wiele metod może mieć podobną nazwę i ten sam prototyp. |
Szybsze wykonywanie, ponieważ wykrywanie metod odbywa się w czasie kompilacji | Wolniejsze wykonywanie, ponieważ wykrywacz metod jest wykonywany w czasie wykonywania. |
Zapewniona jest mniejsza elastyczność w rozwiązywaniu problemów, ponieważ wszystko jest znane w czasie kompilacji. | Zapewnia się dużą elastyczność w rozwiązywaniu złożonych problemów, ponieważ metody są odkrywane w czasie wykonywania. |
Podsumowanie:
- Polimorfizm oznacza wiele form.
- Występuje, gdy istnieje hierarchia klas powiązanych przez dziedziczenie.
- W przypadku polimorfizmu funkcja może zachowywać się inaczej w zależności od obiektu, który ją wywołuje / wywołuje.
- W polimorfizmie w czasie kompilacji wywoływana funkcja jest ustalana w czasie kompilacji.
- W polimorfizmie środowiska uruchomieniowego funkcja, która ma zostać wywołana, jest ustalana w czasie wykonywania.
- Polimorfizm w czasie kompilacji jest określany przez przeciążanie funkcji i przeciążanie operatorów.
- W przypadku przeciążania funkcji istnieje wiele funkcji o podobnych nazwach, ale różnych argumentach.
- Parametry mogą różnić się liczbą lub typem.
- W przypadku przeciążania operatorów zdefiniowano nowe znaczenie dla operatorów C ++.
- Polimorfizm w czasie wykonywania jest osiągany poprzez nadpisywanie funkcji.
- W przypadku przesłaniania funkcji klasa pochodna nadaje nową definicję funkcji zdefiniowanej w klasie bazowej.