logo

Operatoroverbelasting in C++

in C++ is overbelasting van operators een polymorfisme tijdens het compileren. Het is een idee om een ​​speciale betekenis te geven aan een bestaande operator in C++ zonder de oorspronkelijke betekenis ervan te veranderen.

In dit artikel gaan we verder in op het overbelasten van operators in C++ met voorbeelden en kijken we welke operators we wel of niet kunnen overbelasten in C++.



Overbelasting van C++-operator

C++ heeft de mogelijkheid om de operators een speciale betekenis te geven voor een gegevenstype. Deze mogelijkheid staat bekend als operator-overbelasting. Overbelasting door operators is een polymorfisme tijdens het compileren. We kunnen bijvoorbeeld een operator ‘+’ in een klasse als String overbelasten, zodat we twee tekenreeksen kunnen samenvoegen door alleen maar + te gebruiken. Andere voorbeeldklassen waarin rekenkundige operatoren overbelast kunnen raken zijn complexe getallen, breukgetallen, grote gehele getallen, enz.

Voorbeeld:

int a; float b,sum; sum = a + b;>

Hier zijn variabelen a en b van het type int en float, wat ingebouwde gegevenstypen zijn. Daarom kan de opteloperator ‘+’ gemakkelijk de inhoud van a en b optellen. Dit komt doordat de opteloperator + vooraf is gedefinieerd om alleen variabelen van het ingebouwde gegevenstype toe te voegen.



Implementatie:

C++




Java-vergelijkingsreeksen



// C++ Program to Demonstrate the> // working/Logic behind Operator> // Overloading> class> A {> >statements;> };> int> main()> {> >A a1, a2, a3;> >a3 = a1 + a2;> >return> 0;> }>

>

>

In dit voorbeeld hebben we 3 variabelen a1, a2 en a3 van type klasse A. Hier proberen we twee objecten a1 en a2 toe te voegen, die van het door de gebruiker gedefinieerde type zijn, d.w.z. van type klasse A, met behulp van de operator +. Dit is niet toegestaan, omdat de opteloperator + vooraf is gedefinieerd om alleen op ingebouwde gegevenstypen te werken. Maar hier is klasse A een door de gebruiker gedefinieerd type, dus de compiler genereert een fout. Dit is waar het concept van overbelasting van de operator om de hoek komt kijken.

Als de gebruiker nu de operator + twee klasseobjecten wil laten toevoegen, moet de gebruiker de betekenis van de + operator opnieuw definiëren, zodat deze twee klasseobjecten toevoegt. Dit wordt gedaan door gebruik te maken van het concept van Operator-overbelasting. Het belangrijkste idee achter overbelasting van operators is dus het gebruik van C++-operatoren met klassevariabelen of klasseobjecten. Het herdefiniëren van de betekenis van operatoren verandert feitelijk niets aan hun oorspronkelijke betekenis; in plaats daarvan hebben ze naast hun bestaande betekenis een extra betekenis gekregen.

Voorbeeld van overbelasting van operators in C++

C++




// C++ Program to Demonstrate> // Operator Overloading> #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 <<>' '>; }> };> int> main()> {> >Complex c1(10, 5), c2(2, 4);> >Complex c3 = c1 + c2;> >c3.print();> }>

>

>

Uitvoer

12 + i9>

Verschil tussen operatorfuncties en normale functies

De operatorfuncties zijn hetzelfde als de normale functies. De enige verschillen zijn dat de naam van een operatorfunctie altijd de trefwoord operator gevolgd door het symbool van de operator, en operatorfuncties worden opgeroepen wanneer de corresponderende operator wordt gebruikt.

Voorbeeld

C++




#include> using> namespace> std;> class> Complex {> private>:> >int> real, imag;> public>:> >Complex(>int> r = 0,>int> i = 0)> >{> >real = r;> >imag = i;> >}> >void> print() { cout << real <<>' + i'> << imag << endl; }> >// The global operator function is made friend of this> >// class so that it can access private members> >friend> Complex operator+(Complex>const>& c1,> >Complex>const>& c2);> };> Complex operator+(Complex>const>& c1, Complex>const>& c2)> {> >return> Complex(c1.real + c2.real, c1.imag + c2.imag);> }> int> main()> {> >Complex c1(10, 5), c2(2, 4);> >Complex c3> >= c1> >+ c2;>// An example call to 'operator+'> >c3.print();> >return> 0;> }>

>

>

Uitvoer

12 + i9>

Kunnen we alle operators overbelasten?

Bijna alle operators kunnen overbelast raken, op enkele na. Hieronder volgt een lijst met operators die niet kunnen worden overbelast.

sizeof typeid Scope resolution (::) Class member access operators (.(dot), .* (pointer to member operator)) Ternary or conditional (?:)>

Operators die overbelast kunnen raken in C++

Wij kunnen overbelasten

    Unaire operatoren Binaire operatoren Speciale operatoren ( [ ], (), enz.)

Maar onder hen zijn er enkele operators die niet overbelast kunnen worden. Zij zijn

    Operator voor bereikresolutie (: Operator voor ledenselectie Ledenselectie via *

Wijzer naar een lidvariabele

    Voorwaardelijke operator (? Sizeof operator sizeof()
Operators die overbelast kunnen raken Voorbeelden
Binaire rekenkunde +, -, *, /, %
Unaire rekenkunde +, -, ++, —
Opdracht =, +=,*=, /=,-=, %=
Bitsgewijs &, | , <> , ~ , ^
Verwijdering van verwijzingen (->)
Dynamische geheugentoewijzing,
De-allocatie
Nieuw, verwijderen
Abonnement [ ]
Functie oproep ()
Logisch &, | |, !
relationeel >, <, = =, =

Waarom kunnen de hierboven genoemde operators niet overbelast worden?

1. grootte van Operator

Dit retourneert de grootte van het object of gegevenstype dat als operand is ingevoerd. Dit wordt geëvalueerd door de compiler en kan niet tijdens runtime worden geëvalueerd. De juiste verhoging van een aanwijzer in een array van objecten is impliciet afhankelijk van de grootte van de operator. Het veranderen van de betekenis ervan door middel van overbelasting zou ertoe leiden dat een fundamenteel deel van de taal instort.

2. typeid-operator

Dit biedt een CPP-programma de mogelijkheid om het feitelijk afgeleide type van het object waarnaar door een pointer of referentie wordt verwezen, te herstellen. Voor deze operator gaat het erom een ​​type uniek te identificeren. Als we een door de gebruiker gedefinieerd type willen laten ‘lijken’ op een ander type, kan polymorfisme worden gebruikt, maar de betekenis van de typeid-operator moet ongewijzigd blijven, anders kunnen er ernstige problemen ontstaan.

3. Bereikresolutie (::) Operator

Dit helpt bij het identificeren en specificeren van de context waarnaar een ID verwijst door een naamruimte op te geven. Het wordt tijdens runtime volledig geëvalueerd en werkt op namen in plaats van op waarden. De operanden van scoperesolutie zijn notitie-expressies met gegevenstypen en CPP heeft geen syntaxis om deze vast te leggen als deze overbelast zou zijn. Het is dus syntactisch onmogelijk om deze operator te overbelasten.

4. Toegangsoperatoren voor klasseleden (.(dot ), .* (aanwijzer naar lidoperator))

Het belang en het impliciete gebruik van toegangsoperatoren voor klasseleden kan worden begrepen aan de hand van het volgende voorbeeld:

Voorbeeld:

C++




// C++ program to demonstrate operator overloading> // using dot operator> #include> using> namespace> std;> class> ComplexNumber {> private>:> >int> real;> >int> imaginary;> public>:> >ComplexNumber(>int> real,>int> imaginary)> >{> >this>->echt = echt;> >this>->denkbeeldig = denkbeeldig;> >}> >void> print() { cout << real <<>' + i'> << imaginary; }> >ComplexNumber operator+(ComplexNumber c2)> >{> >ComplexNumber c3(0, 0);> >c3.real =>this>->echt + c2.real;> >c3.imaginary =>this>->denkbeeldig + c2.imaginair;> >return> c3;> >}> };> int> main()> {> >ComplexNumber c1(3, 5);> >ComplexNumber c2(2, 4);> >ComplexNumber c3 = c1 + c2;> >c3.print();> >return> 0;> }>

>

>

Uitvoer

5 + i9>

Uitleg:

De verklaring ComplexGetal c3 = c1 + c2; wordt intern vertaald als ComplexNumber c3 = c1.operator+ (c2); om de operatorfunctie op te roepen. Het argument c1 wordt impliciet doorgegeven met behulp van de '.' exploitant. De volgende instructie maakt ook gebruik van de puntoperator om toegang te krijgen tot de lidfunctie print en c3 als argument door te geven.

Bovendien werken deze operators ook met namen en niet met waarden, en er is geen voorziening (syntactisch) om ze te overbelasten.

5. Ternaire of voorwaardelijke (?:) Operator

De ternaire of voorwaardelijke operator is een verkorte weergave van een if-else-instructie. In de operator worden de waar/onwaar-uitdrukkingen alleen geëvalueerd op basis van de waarheidswaarde van de voorwaardelijke uitdrukking.

conditional statement ? expression1 (if statement is TRUE) : expression2 (else)>

Een functie die de ternaire operator voor een klasse overbelast, zegt ABC met behulp van de definitie

ABC operator ?: (bool condition, ABC trueExpr, ABC falseExpr);>

zou niet kunnen garanderen dat slechts één van de uitdrukkingen werd geëvalueerd. De ternaire operator kan dus niet overbelast worden.

Belangrijke punten over overbelasting van de operator

1) Om overbelasting door operators te laten werken, moet ten minste één van de operanden een door de gebruiker gedefinieerd klassenobject zijn.

2) Toewijzingsoperator: Compiler maakt bij elke klasse automatisch een standaardtoewijzingsoperator. De standaardtoewijzingsoperator wijst alle leden van de rechterkant toe aan de linkerkant en werkt in de meeste gevallen prima (dit gedrag is hetzelfde als de kopieerconstructor). Zie dit voor meer details.

3) Conversie-operator: We kunnen ook conversie-operatoren schrijven die kunnen worden gebruikt om het ene type naar het andere type te converteren.

Voorbeeld:

C++




// C++ Program to Demonstrate the working> // of conversion operator> #include> using> namespace> std;> class> Fraction {> private>:> >int> num, den;> public>:> >Fraction(>int> n,>int> d)> >{> >num = n;> >den = d;> >}> >// Conversion operator: return float value of fraction> >operator>float>()>const> >{> >return> float>(num) />float>(den);> >}> };> int> main()> {> >Fraction f(2, 5);> >float> val = f;> >cout << val <<>' '>;> >return> 0;> }>

>

>

Uitvoer

0.4>

Overbelaste conversie-operators moeten een lidmethode zijn. Andere operators kunnen de lidmethode of de globale methode zijn.

hoe verborgen apps te onthullen

4) Elke constructor die met een enkel argument kan worden aangeroepen, werkt als een conversieconstructor, wat betekent dat hij ook kan worden gebruikt voor impliciete conversie naar de klasse die wordt geconstrueerd.

Voorbeeld:

C++




// C++ program to demonstrate can also be used for implicit> // conversion to the class being constructed> #include> using> namespace> std;> class> Point {> private>:> >int> x, y;> public>:> >Point(>int> i = 0,>int> j = 0)> >{> >x = i;> >y = j;> >}> >void> print()> >{> >cout <<>'x = '> << x <<>', y = '> << y <<>' '>;> >}> };> int> main()> {> >Point t(20, 20);> >t.print();> >t = 30;>// Member x of t becomes 30> >t.print();> >return> 0;> }>

>

>

Uitvoer

x = 20, y = 20 x = 30, y = 0>

Quiz over overbelasting van operators