Polimorfizm C++

Polimorfizm C++

Słowo polimorfizm oznacza posiadanie wielu form. W prostych słowach możemy zdefiniować polimorfizm jako zdolność komunikatu do wyświetlania w więcej niż jednej formie. Prawdziwym przykładem polimorfizmu jest osoba, która jednocześnie może mieć różne cechy. Mężczyzna jest jednocześnie ojcem, mężem i pracownikiem. Zatem ta sama osoba zachowuje się inaczej w różnych sytuacjach. Nazywa się to polimorfizmem. Polimorfizm jest uważany za jedną z ważnych cech programowania obiektowego.

Rodzaje polimorfizmu

  • Polimorfizm w czasie kompilacji
  • Polimorfizm środowiska wykonawczego
Rodzaje polimorfizmu

Rodzaje polimorfizmu

1. Polimorfizm w czasie kompilacji

Ten typ polimorfizmu osiąga się poprzez przeciążenie funkcji lub przeciążenie operatora.

A. Przeciążenie funkcji

Gdy istnieje wiele funkcji o tej samej nazwie, ale różnych parametrach, wówczas mówi się, że funkcje te są przeciążony, dlatego nazywa się to przeciążaniem funkcji. Funkcje mogą być przeciążane przez zmiana liczby argumentów albo i zmiana rodzaju argumentów . Mówiąc najprościej, jest to cecha programowania obiektowego zapewniająca wiele funkcji o tej samej nazwie, ale różnych parametrach, gdy wiele zadań jest wymienionych pod jedną nazwą funkcji. Istnieją pewne zasady przeciążania funkcji, których należy przestrzegać podczas przeciążania funkcji.

Poniżej znajduje się program C++ pokazujący przeciążanie funkcji lub polimorfizm w czasie kompilacji:

C++




// C++ program to demonstrate> // function overloading or> // Compile-time Polymorphism> #include> using> namespace> std;> class> Geeks {> public> :> > // Function with 1 int parameter> > void> func(> int> x)> > {> > cout < <> 'value of x is '> < < x < < endl;> > }> > // Function with same name but> > // 1 double parameter> > void> func(> double> x)> > {> > cout < <> 'value of x is '> < < x < < endl;> > }> > // Function with same name and> > // 2 int parameters> > void> func(> int> x,> int> y)> > {> > cout < <> 'value of x and y is '> < < x < <> ', '> < < y> > < < endl;> > }> };> // Driver code> int> main()> {> > Geeks obj1;> > // Function being called depends> > // on the parameters passed> > // func() is called with int value> > obj1.func(7);> > // func() is called with double value> > obj1.func(9.132);> > // func() is called with 2 int values> > obj1.func(85, 64);> > return> 0;> }>

Wyjście

value of x is 7 value of x is 9.132 value of x and y is 85, 64 

Wyjaśnienie: W powyższym przykładzie pojedyncza funkcja o nazwie funkcja funkcja() zachowuje się inaczej w trzech różnych sytuacjach, co jest właściwością polimorfizmu. Aby dowiedzieć się więcej na ten temat, możesz zapoznać się z artykułem – Przeciążanie funkcji w C++ .

B. Przeciążenie operatora

C++ ma możliwość nadawania operatorom specjalnego znaczenia dla typu danych. Zdolność ta nazywana jest przeciążaniem operatora. Na przykład możemy użyć operatora dodawania (+) dla klasy string, aby połączyć dwa ciągi. Wiemy, że zadaniem tego operatora jest dodanie dwóch operandów. Zatem pojedynczy operator „+” umieszczony pomiędzy operandami całkowitymi dodaje je, a umieszczony pomiędzy operandami łańcuchowymi łączy je.

Poniżej znajduje się program C++ demonstrujący przeciążenie operatora:

CPP




// C++ program to demonstrate> // Operator Overloading or> // Compile-Time Polymorphism> #include> using> namespace> std;> class> Complex {> private> :> > int> real, imag;> public> :> > Complex(> int> r = 0,> int> i = 0)> > {> > real = r;> > imag = i;> > }> > // This is automatically called> > // when '+' is used with between> > // two Complex objects> > Complex operator+(Complex> const> & obj)> > {> > Complex res;> > res.real = real + obj.real;> > res.imag = imag + obj.imag;> > return> res;> > }> > void> print() { cout < < real < <> ' + i'> < < imag < < endl; }> };> // Driver code> int> main()> {> > Complex c1(10, 5), c2(2, 4);> > // An example call to 'operator+'> > Complex c3 = c1 + c2;> > c3.print();> }>

Wyjście

12 + i9 

Wyjaśnienie: W powyższym przykładzie operator „+” jest przeciążony. Zwykle ten operator służy do dodawania dwóch liczb (liczb całkowitych lub zmiennoprzecinkowych), ale w tym przypadku operator ma na celu wykonanie dodania dwóch liczb urojonych lub zespolonych. Aby dowiedzieć się więcej na ten temat, zapoznaj się z artykułem – Przeciążenie operatora .

2. Polimorfizm środowiska wykonawczego

Ten typ polimorfizmu osiąga się poprzez Zastąpienie funkcji . Późne wiązanie i dynamiczny polimorfizm to inne nazwy polimorfizmu w czasie wykonywania. Wywołanie funkcji jest rozwiązywane w czasie wykonywania in polimorfizm czasu wykonywania . W przeciwieństwie do tego, w przypadku polimorfizmu czasu kompilacji, kompilator określa, które wywołanie funkcji ma zostać powiązane z obiektem, po wywnioskowaniu tego w czasie wykonywania.

A. Zastąpienie funkcji

Zastąpienie funkcji występuje, gdy klasa pochodna ma definicję jednej z funkcji składowych klasy bazowej. Mówi się, że ta funkcja podstawowa została przesłonięta.

Przesłanianie funkcji w C++

Funkcja przesłaniająca Wyjaśnienie

Polimorfizm środowiska wykonawczego ze składnikami danych

Elementy członkowskie danych w języku C++ nie mogą osiągnąć polimorfizmu środowiska wykonawczego. Zobaczmy przykład, w którym uzyskujemy dostęp do pola poprzez zmienną referencyjną klasy nadrzędnej, która odwołuje się do instancji klasy pochodnej.

C++




// C++ program for function overriding with data members> #include> using> namespace> std;> // base class declaration.> class> Animal {> public> :> > string color => 'Black'> ;> };> // inheriting Animal class.> class> Dog :> public> Animal {> public> :> > string color => 'Grey'> ;> };> // Driver code> int> main(> void> )> {> > Animal d = Dog();> // accessing the field by reference> > // variable which refers to derived> > cout < < d.color;> }>

Wyjście

Black 

Widzimy, że odwołanie do klasy nadrzędnej zawsze będzie odnosić się do elementu danych klasy nadrzędnej.

B. Funkcja wirtualna

A funkcja wirtualna jest funkcją członkowską zadeklarowaną w klasie bazowej przy użyciu słowa kluczowego virtual i ponownie zdefiniowaną (przesłoniętą) w klasie pochodnej.

Kilka kluczowych punktów na temat funkcji wirtualnych:

  • Funkcje wirtualne mają charakter dynamiczny.
  • Definiuje się je poprzez wstawienie słowa kluczowego wirtualny wewnątrz klasy bazowej i zawsze są deklarowane z klasą bazową i zastępowane w klasie podrzędnej
  • Funkcja wirtualna jest wywoływana w czasie wykonywania

Poniżej znajduje się program C++ demonstrujący funkcję wirtualną:

C++




// C++ Program to demonstrate> // the Virtual Function> #include> using> namespace> std;> // Declaring a Base class> class> GFG_Base {> public> :> > // virtual function> > virtual> void> display()> > {> > cout < <> 'Called virtual Base Class function'> > < <> ' '> ;> > }> > void> print()> > {> > cout < <> 'Called GFG_Base print function'> > < <> ' '> ;> > }> };> // Declaring a Child Class> class> GFG_Child :> public> GFG_Base {> public> :> > void> display()> > {> > cout < <> 'Called GFG_Child Display Function'> > < <> ' '> ;> > }> > void> print()> > {> > cout < <> 'Called GFG_Child print Function'> > < <> ' '> ;> > }> };> // Driver code> int> main()> {> > // Create a reference of class GFG_Base> > GFG_Base* base;> > GFG_Child child;> > base = &child;> > // This will call the virtual function> > base->GFG_Base::display();> > // this will call the non-virtual function> > base->drukuj();> }>

Wyjście

Called virtual Base Class function Called GFG_Base print function 

Przykład 2:

C++




// C++ program for virtual function overriding> #include> using> namespace> std;> class> base {> public> :> > virtual> void> print()> > {> > cout < <> 'print base class'> < < endl;> > }> > void> show() { cout < <> 'show base class'> < < endl; }> };> class> derived :> public> base {> public> :> > // print () is already virtual function in> > // derived class, we could also declared as> > // virtual void print () explicitly> > void> print() { cout < <> 'print derived class'> < < endl; }> > void> show() { cout < <> 'show derived class'> < < endl; }> };> // Driver code> int> main()> {> > base* bptr;> > derived d;> > bptr = &d;> > // Virtual function, binded at> > // runtime (Runtime polymorphism)> > bptr->drukuj();> > // Non-virtual function, binded> > // at compile time> > bptr->pokaż();> > return> 0;> }>

Wyjście

print derived class show base class