Preopterećenje i redefiniranje funkcija c. Inline (ugrađene) funkcije. Preopterećenje funkcije. Argumenti sa zadanim vrijednostima

Preopterećenje funkcije je definicija nekoliko funkcija (dvije ili više) s istim imenom, ali različitim parametrima. Skupovi parametara preopterećenih funkcija mogu se razlikovati po redoslijedu, broju i tipu. Stoga je preopterećenje funkcija potrebno kako bi se izbjeglo dupliciranje imena funkcija koje obavljaju slične radnje, ali s različitom programskom logikom. Na primjer, razmotrite funkciju areaRectangle() koja izračunava površinu pravokutnika.

Float areaRectangle(float, float) //funkcija koja izračunava površinu pravokutnika sa dva parametra a(cm) i b(cm) (vraćanje a*b; // množimo dužine stranica pravokutnika i vraćamo rezultirajući proizvod)

Dakle, ovo je funkcija sa dva parametra tipa float, a argumenti koji se prosljeđuju funkciji moraju biti u centimetrima, povratna vrijednost tipa float je također u centimetrima.

Pretpostavimo da su naši početni podaci (stranice pravougaonika) dati u metrima i centimetrima, na primjer: a = 2m 35 cm; b = 1m 86 cm U ovom slučaju bi bilo zgodno koristiti funkciju sa četiri parametra. To jest, svaka dužina stranica pravokutnika se prosljeđuje funkciji u dva parametra: metrima i centimetrima.

Float areaRectangle(float a_m, float a_sm, float b_m, float b_sm) // funkcija koja izračunava površinu pravokutnika sa 4 parametra a(m) a(cm); b(m) b(cm) ( povratak (a_m * 100 + a_sm) * (b_m * 100 + b_sm); )

U tijelu funkcije, vrijednosti koje su proslijeđene u metrima (a_m i b_m) se pretvaraju u centimetre i dodaju vrijednostima a_sm b_sm, nakon čega pomnožimo zbrojeve i dobijemo površinu pravokutnika u cm Naravno, bilo je moguće konvertovati originalne podatke u centimetre i koristiti prvu funkciju, ali sada nije o tome.

E sad, najvažnije je da imamo dvije funkcije, sa različitim potpisima, ali istim imenom (preopterećene funkcije). Potpis je kombinacija imena funkcije sa njenim parametrima. Kako nazvati ove funkcije? A pozivanje preopterećenih funkcija se ne razlikuje od pozivanja redovnih funkcija, na primjer:

AreaRectangle(32, 43); // bit će pozvana funkcija koja izračunava površinu pravokutnika sa dva parametra a(cm) i b(cm) areaRectangle(4, 43, 2, 12); // bit će pozvana funkcija koja izračunava površinu pravokutnika sa 4 parametra a(m) a(cm); b(m) b(cm)

Kao što vidite, kompajler će samostalno odabrati željenu funkciju, analizirajući samo potpise preopterećenih funkcija. Zaobilazeći preopterećenje funkcije, jednostavno bi se mogla deklarirati funkcija s drugim imenom i ona bi dobro radila svoj posao. Ali zamislite šta će se dogoditi ako vam treba više od dvije takve funkcije, na primjer 10. I za svaku morate smisliti smisleno ime, a najteže ih je zapamtiti. Upravo zbog toga je lakše i bolje preopteretiti funkcije, osim ako za tim nema potrebe. Izvorni kod programa je prikazan ispod.

#include "stdafx.h" #include << "S1 = " << areaRectangle(32,43) << endl; // вызов перегруженной функции 1 cout << "S2 = " << areaRectangle(4, 43, 2, 12) << endl; // вызов перегруженной функции 2 return 0; } // перегруженная функция 1 float areaRectangle(float a, float b) //функция, вычисляющая площадь прямоугольника с двумя параметрами a(см) и b(см) { return a * b; // умножаем длинны сторон прямоугольника и возвращаем полученное произведение } // перегруженная функция 2 float areaRectangle(float a_m, float a_sm, float b_m, float b_sm) // функция, вычисляющая площадь прямоугольника с 4-мя параметрами a(м) a(см); b(м) b(cм) { return (a_m * 100 + a_sm) * (b_m * 100 + b_sm); }

// kod Code::Blocks

// Dev-C++ kod

#include korištenje imenskog prostora std; // prototipovi preopterećenih funkcija float areaRectangle(float a, float b); float areaRectangle(float a_m, float a_sm, float b_m, float b_sm); int main() ( cout<< "S1 = " << areaRectangle(32,43) << endl; // вызов перегруженной функции 1 cout << "S2 = " << areaRectangle(4, 43, 2, 12) << endl; // вызов перегруженной функции 2 return 0; } // перегруженная функция 1 float areaRectangle(float a, float b) //функция, вычисляющая площадь прямоугольника с двумя параметрами a(см) и b(см) { return a * b; // умножаем длинны сторон прямоугольника и возвращаем полученное произведение } // перегруженная функция 2 float areaRectangle(float a_m, float a_sm, float b_m, float b_sm) // функция, вычисляющая площадь прямоугольника с 4-мя параметрами a(м) a(см); b(м) b(cм) { return (a_m * 100 + a_sm) * (b_m * 100 + b_sm); }

Rezultat programa je prikazan na slici 1.

Kada definirate funkcije u svojim programima, morate specificirati tip povratka funkcije, kao i broj parametara i tip svakog parametra. U prošlosti (ako ste programirali u C), kada ste imali funkciju zvanu add_values ​​koja je radila na dvije cjelobrojne vrijednosti, a željeli ste koristiti sličnu funkciju za dodavanje tri cjelobrojne vrijednosti, trebali ste kreirati funkciju sa drugačije ime. Na primjer, možete koristiti add_two_values ​​i add_three_values. Slično, ako želite koristiti sličnu funkciju za dodavanje float vrijednosti, tada bi vam trebala druga funkcija s drugim imenom. Da biste izbjegli dupliciranje funkcija, C++ vam omogućava da definirate više funkcija s istim imenom. Tokom kompilacije, C++ uzima u obzir broj argumenata koje koristi svaka funkcija i zatim poziva tačno traženu funkciju. Davanje kompajleru izbora između više funkcija naziva se preopterećenje. U ovom vodiču ćete naučiti kako koristiti preopterećene funkcije. Do kraja ove lekcije savladat ćete sljedeće osnovne koncepte:

Preopterećenje funkcija vam omogućava da koristite isto ime za više funkcija s različitim tipovima parametara.

Za preopterećenje funkcija jednostavno definirajte dvije funkcije s istim imenom i tipom povrata koje se razlikuju po broju parametara ili njihovom tipu.

Preopterećenje funkcija je karakteristika jezika C++ koja se ne nalazi u C. Kao što ćete vidjeti, preopterećenje funkcija je prilično zgodno i može poboljšati čitljivost vaših programa.

PRVI UVOD U PREOPTERETANJE FUNKCIJA

Preopterećenje funkcija omogućava vašim programima da definiraju više funkcija s istim imenom i tipom povrata. Na primjer, sljedeći program preopterećuje funkciju pod nazivom add_values. Prva definicija funkcije dodaje dvije int vrijednosti. Druga definicija funkcije dodaje tri vrijednosti. Tokom kompilacije, C++ ispravno određuje funkciju koja će se koristiti:

#include

int add_values(int a,int b)

{
return(a+b);
)

int add_values ​​(int a, int b, int c)

(
return(a+b+c);
)

{
cout<< «200 + 801 = » << add_values(200, 801) << endl;
cout<< «100 + 201 + 700 = » << add_values(100, 201, 700) << endl;
}

Kao što vidite, program definira dvije funkcije pod nazivom add_values.Prva funkcija dodaje dvije int vrijednosti, dok druga dodaje tri vrijednosti. Ne morate ništa posebno raditi da biste kompajlera upozorili na preopterećenje, samo ga koristite. Kompajler će shvatiti koju funkciju koristiti na osnovu opcija koje program nudi.

Slično, sljedeći program MSG_OVR.CPP preopterećuje funkciju show_message. Prva funkcija pod nazivom show_message prikazuje standardnu ​​poruku, nikakvi parametri joj se ne prosljeđuju. Drugi šalje poruku koja mu je proslijeđen, a treći dvije poruke:

#include

void show_message(void)

{
cout<< «Стандартное сообщение: » << «Учимся программировать на C++» << endl;
}

void show_message(char *message)

{
cout<< message << endl;
}

void show_message(char *prvi, char *drugi)

{
cout<< first << endl;
cout<< second << endl;
}

{
show_message();
show_message("Naučite programirati u C++!");
show_message("U C++ nema predrasuda!", "Preopterećenje je cool!");
}

KADA JE PREOPTEREĆENJE POTREBNO

Jedan od najčešćih slučajeva preopterećenja je korištenje funkcije za proizvodnju određenog rezultata s obzirom na različite parametre. Na primjer, pretpostavimo da vaš program ima funkciju pod nazivom day_of_week koja vraća trenutni dan u sedmici (0 za nedjelju, 1 za ponedjeljak, ..., 6 za subotu). Vaš program bi mogao preopteretiti ovu funkciju tako da ispravno vraća dan u sedmici ako mu je dat julijanski dan kao parametar ili ako mu je dan, mjesec i godina:

int dan_sedmice(int julian_dan)

{
// Operatori
}

int dan_sedmice(int mjesec, int dan, int godina)

{
// Operatori
}

Dok istražujete objektno orijentirano programiranje u C++ u sljedećim lekcijama, koristit ćete preopterećenje funkcija da proširite snagu svojih programa.

Preopterećenje funkcija poboljšava čitljivost programa

Preopterećenje C++ funkcija omogućava vašim programima da definiraju više funkcija s istim imenom. Preopterećene funkcije moraju vratiti vrijednosti istog tipa*, ali se mogu razlikovati po broju i vrsti parametara. Prije pojave preopterećenja funkcija u C++, C programeri su morali kreirati više funkcija sa skoro istim imenom. Nažalost, programeri koji su željeli koristiti takve funkcije morali su zapamtiti koja kombinacija parametara odgovara kojoj funkciji. S druge strane, preopterećenje funkcija pojednostavljuje zadatak programera zahtijevajući od njih da zapamte samo jedno ime funkcije.* Preopterećene funkcije nisu potrebne za vraćanje vrijednosti istog tipa, jer kompajler jedinstveno identificira funkciju po njenom imenu i njenom nazivu. skup argumenata. Za kompajler, funkcije s istim imenom, ali različitim tipovima argumenata su različite funkcije, tako da je tip povratka prerogativ svake funkcije. - Approx.transl.

ŠTA TREBA ZNATI

Preopterećenje funkcije vam omogućava da specificirate više definicija za istu funkciju. Tokom kompilacije, C++ će odrediti koju funkciju će koristiti na osnovu broja i tipa proslijeđenih parametara. U ovom vodiču ste naučili da je lako preopteretiti funkcije. U lekciji 14 naučit ćete kako C++ reference olakšavaju promjenu parametara unutar funkcija. Međutim, prije nego što pređete na lekciju 14, provjerite jeste li naučili sljedeće osnovne koncepte:

  1. Preopterećenje funkcija pruža višestruke "preglede" iste funkcije unutar vašeg programa.
  2. Da biste preopteretili funkcije, jednostavno definirajte više funkcija s istim imenom i tipom povrata koji se razlikuju samo po broju i vrsti parametara.
  3. Tokom kompilacije, C++ će odrediti koju funkciju će pozvati na osnovu broja i tipa proslijeđenih parametara.
  4. Preopterećenje funkcija pojednostavljuje programiranje dozvoljavajući programerima da rade sa samo jednim imenom funkcije.

Preopterećenje funkcije

Preopterećenje operacija (operateri, funkcije, procedure)- u programiranju - jedan od načina implementacije polimorfizma, koji se sastoji u mogućnosti istovremenog postojanja u jednom opsegu više različitih varijanti operacije (operator, funkcija ili procedura) koje imaju isti naziv, ali se razlikuju po vrstama parametara na koje se primenjuju.

Terminologija

Termin "preopterećenje" je paus papir engleskog "overloading", koji se pojavio u ruskim prijevodima knjiga o programskim jezicima u prvoj polovini 1990-ih. Možda ovo nije najbolja opcija prijevoda, budući da riječ "preopterećenje" na ruskom ima vlastito utvrđeno značenje, radikalno drugačije od novopredloženog, međutim, zaživjelo je i prilično je rašireno. U publikacijama sovjetske ere, slični mehanizmi na ruskom su nazivani "redefinicija" ili "redefinicija" operacija, ali ova opcija nije sporna: neslaganja i konfuzija nastaju u prijevodima engleskog "preklapanje", "preopterećenje" i " redefiniraj”.

Razlozi za pojavu

Većina ranih programskih jezika imala je ograničenje da u programu ne može biti dostupno više od jedne operacije s istim imenom u isto vrijeme. Shodno tome, sve funkcije i procedure vidljive u datoj tački programa moraju imati različita imena. Nazive i oznake funkcija, procedura i operatora koji su dio programskog jezika programer ne može koristiti da imenuje svoje funkcije, procedure i operatore. U nekim slučajevima, programer može kreirati vlastiti programski objekt s imenom drugog već postojećeg, ali tada se novonastali objekt „preklapa“ s prethodnim i postaje nemoguće koristiti obje opcije istovremeno.

Ova situacija je nezgodna u nekim prilično čestim slučajevima.

  • Ponekad postoji potreba za opisivanjem i primjenom operacija na tipove podataka koje je kreirao programer koji su po značenju ekvivalentni onima koji su već dostupni u jeziku. Klasičan primjer je biblioteka za rad sa kompleksnim brojevima. Oni, kao i obični numerički tipovi, podržavaju aritmetičke operacije i bilo bi prirodno za ovu vrstu operacija kreirati "plus", "minus", "množenje", "dijeli", označavajući ih istim znakovima operacija kao i za druge numeričke vrste. Zabrana upotrebe elemenata definiranih u jeziku prisiljava stvaranje mnogih funkcija s imenima kao što su ComplexPlusComplex, IntegerPlusComplex, ComplexMinusFloat, itd.
  • Kada se operacije istog značenja primjenjuju na operande različitih tipova, oni su prisiljeni da budu drugačije imenovani. Nemogućnost korištenja funkcija s istim imenom za različite tipove funkcija dovodi do potrebe da se izmišljaju različiti nazivi za istu stvar, što stvara zabunu i čak može dovesti do grešaka. Na primjer, u klasičnom jeziku C postoje dvije verzije standardne bibliotečke funkcije za pronalaženje modula broja: abs() i fabs() - prva je namijenjena za cjelobrojni argument, druga za realni. Ova situacija, u kombinaciji sa slabom provjerom C tipa, može dovesti do greške koju je teško pronaći: ako programer zapiše abs(x) u proračunu, gdje je x realna varijabla, onda će neki prevodioci generirati kod bez upozorenja koji će pretvoriti x u cijeli broj odbacivanjem razlomaka i izračunati modul iz rezultirajućeg cijelog broja!

Djelomično se problem rješava pomoću objektnog programiranja – kada se novi tipovi podataka deklariraju kao klase, operacije nad njima mogu se formalizirati kao metode klase, uključujući i metode klase istog imena (pošto metode različitih klasa ne moraju imati različita imena), ali, prvo, takav dizajn način rada na vrijednostima različitih tipova je nezgodan, a drugo, ne rješava problem stvaranja novih operatora.

Preopterećenje operatora samo po sebi je samo "sintaktički šećer", iako čak i kao takvo može biti korisno jer omogućava programeru da programira na prirodniji način i čini prilagođene tipove da se ponašaju više kao ugrađeni. Ako problemu pristupimo s općenitije pozicije, onda možemo vidjeti da alati koji vam omogućavaju da proširite jezik, dopunite ga novim operacijama i sintaksičkim konstrukcijama (a preopterećenje operacija je jedan od takvih alata, zajedno sa objektima, makroima , funkcionalnosti, zatvaranja) pretvaraju ga već u metajezik - sredstvo za opisivanje jezika orijentiranih na specifične zadatke. Uz njegovu pomoć moguće je izgraditi jezičko proširenje za svaki konkretan zadatak koji mu najviše odgovara, što će omogućiti da se njegovo rješenje opiše u najprirodnijem, razumljivijem i jednostavnom obliku. Na primjer, u aplikaciji za operacije preopterećenja: kreiranje biblioteke složenih matematičkih tipova (vektori, matrice) i opisivanje operacija s njima u prirodnom, "matematičkom" obliku, stvara "jezik za vektorske operacije", u kojem je složenost proračuni su skriveni, a moguće je opisati rješenje problema u terminima vektorskih i matričnih operacija, fokusirajući se na suštinu problema, a ne na tehniku. Iz tih razloga su takva sredstva nekada bila uključena u jezik Algol-68.

Mehanizam preopterećenja

Implementacija

Preopterećenje operatora uključuje uvođenje dvije međusobno povezane značajke u jezik: mogućnost deklariranja nekoliko procedura ili funkcija s istim imenom u istom opsegu i mogućnost opisivanja vlastitih implementacija operacija (odnosno znakova operacija, obično napisano infiksnom notacijom, između operanada). U osnovi, njihova implementacija je prilično jednostavna:

  • Da bi se omogućilo postojanje nekoliko operacija istog imena, dovoljno je uvesti u jezik pravilo prema kojem se operacija (procedura, funkcija ili operator) prepoznaje od strane kompajlera ne samo po imenu (notaciji), već takođe po vrstama njihovih parametara. Dakle, abs(i), gdje je i deklarirano kao cijeli broj, i abs(x), gdje je x deklarirano kao realno, dvije su različite operacije. U osnovi, nema poteškoća u pružanju upravo takvog tumačenja.
  • Da bi se omogućilo definiranje i redefiniranje operacija, potrebno je u jezik uvesti odgovarajuće sintaksičke konstrukcije. Može biti dosta opcija, ali u stvari se ne razlikuju jedna od druge, dovoljno je zapamtiti da je unos obrasca “<операнд1> <знакОперации> <операнд2>» je u osnovi slično pozivanju funkcije «<знакОперации>(<операнд1>,<операнд2>)". Dovoljno je dozvoliti programeru da opiše ponašanje operatora u obliku funkcija - i problem opisa je riješen.

Opcije i problemi

Preopterećenje procedura i funkcija na nivou opšte ideje, po pravilu, nije teško ni implementirati ni razumeti. Međutim, čak iu njemu postoje neke "zamke" koje se moraju uzeti u obzir. Dozvoljavanje preopterećenja operatora stvara mnogo više problema i za implementatora jezika i za programera koji radi na tom jeziku.

Problem identifikacije

Prvo pitanje sa kojim se susreće programer jezičkog prevodioca koji dozvoljava preopterećenje procedura i funkcija je: kako između istoimenih procedura izabrati onu koju treba primeniti u ovom konkretnom slučaju? Sve je u redu ako postoji varijanta procedure čiji se tipovi formalnih parametara tačno poklapaju sa tipovima stvarnih parametara koji se koriste u ovom pozivu. Međutim, u skoro svim jezicima postoji određeni stepen slobode u upotrebi tipova, pod pretpostavkom da kompajler automatski vrši konverzije bezbedne za tipove u određenim situacijama. Na primjer, u aritmetičkim operacijama nad realnim i cjelobrojnim argumentima, cijeli broj se obično automatski pretvara u realni tip, a rezultat je realan. Pretpostavimo da postoje dvije varijante funkcije dodavanja:

int add(int a1, int a2); float add(float a1, float a2);

Kako kompajler treba da rukuje izrazom y = add(x, i) gde je x float, a i int? Očigledno ne postoji tačno podudaranje. Postoje dvije opcije: ili y=add_int((int)x,i) ili kao y=add_flt(x, (float)i) (ovdje nazivi add_int i add_float označavaju prvu i drugu verziju funkcije, respektivno) .

Postavlja se pitanje: treba li kompajler dozvoliti ovu upotrebu preopterećenih funkcija, i ako da, na osnovu čega će odabrati određenu varijantu koja se koristi? Konkretno, u gornjem primjeru, treba li prevodilac uzeti u obzir tip varijable y prilikom odabira? Treba napomenuti da je gornja situacija najjednostavnija, mogući su mnogo složeniji slučajevi, koji su otežani činjenicom da se ne samo ugrađeni tipovi mogu konvertirati prema pravilima jezika, već i klase koje je deklarirao programer. , ako imaju rodbinske odnose, mogu se baciti jedno na drugo. Postoje dva rješenja za ovaj problem:

  • Uopšte zabraniti netačnu identifikaciju. Zahtijevajte da za svaki određeni par tipova postoji tačno odgovarajuća varijanta preopterećene procedure ili operacije. Ako ne postoji takva opcija, kompajler bi trebao izbaciti grešku. Programer u ovom slučaju mora primijeniti eksplicitnu konverziju da prevede stvarne parametre na željeni skup tipova. Ovaj pristup je nezgodan u jezicima kao što je C++, koji dopuštaju priličnu količinu slobode u radu s tipovima, jer dovodi do značajne razlike u ponašanju ugrađenih i preopterećenih operatora (aritmetičke operacije se mogu primijeniti na obične brojeve bez razmišljanja, već na druge vrste - samo uz eksplicitnu konverziju) ili do pojave ogromnog broja opcija za operacije.
  • Uspostavite određena pravila za odabir „najbližeg uklapanja“. Obično u ovoj varijanti kompajler bira one varijante čiji se pozivi mogu dobiti iz izvora samo sigurnim (informacija bez gubitaka) konverzijama tipa, a ako ih ima više, može izabrati na osnovu koje varijante zahtijeva manje takve konverzije. Ako rezultat ostavlja više od jedne mogućnosti, kompajler izbacuje grešku i zahtijeva od programera da eksplicitno specificira varijantu.

Specifični problemi preopterećenja operacija

Za razliku od procedura i funkcija, infiksne operacije programskih jezika imaju dva dodatna svojstva koja značajno utječu na njihovu funkcionalnost: prioritet i asocijativnost, čija je prisutnost posljedica mogućnosti "lančanog" snimanja operatora (kako razumjeti a + b * c: kao (a + b )*c ili kao a+(b*c) ? Izraz a-b+c je (a-b)+c ili a-(b+c) ?).

Operacije ugrađene u jezik uvijek imaju unaprijed definirano tradicionalno prvenstvo i asocijativnost. Postavlja se pitanje: koje će prioritete i asocijativnost imati redefinisane verzije ovih operacija ili, štaviše, nove operacije koje kreira programer? Postoje i druge suptilnosti koje bi mogle zahtijevati pojašnjenje. Na primjer, u C postoje dva oblika inkrementnih i dekrementnih operatora ++ i -- - prefiksa i postfiksa, koji se ponašaju različito. Kako bi se trebale ponašati preopterećene verzije takvih operatora?

Različiti jezici rješavaju ove probleme na različite načine. Dakle, u C++, prioritet i asocijativnost preopterećenih verzija operatora ostaju isti kao oni definisani u jeziku; moguće je odvojeno preopteretiti prefiks i postfiks forme operatora inkrementa i dekrementa koristeći posebne potpise:

Dakle, int se koristi da napravi razliku u potpisima

Najava novih operacija

Situacija s najavom novih operacija je još složenija. Uključivanje mogućnosti takve deklaracije na jeziku nije teško, ali njena implementacija je puna značajnih poteškoća. Deklarisanje nove operacije je, u stvari, kreiranje nove ključne reči programskog jezika, što je komplikovano činjenicom da operacije u tekstu obično mogu da prate druge tokene bez graničnika. Kada se pojave, javljaju se dodatne poteškoće u organizaciji leksičkog analizatora. Na primjer, ako jezik već ima operacije “+” i unarno “-” (promjena predznaka), onda se izraz a+-b može precizno interpretirati kao + (-b), ali ako nova operacija +- je deklarisan u programu, odmah nastaje dvosmislenost, jer se isti izraz već može raščlaniti kao a (+-) b . Programer i implementator jezika moraju se na neki način nositi s takvim problemima. Opcije, opet, mogu biti različite: zahtijevati da sve nove operacije budu jednoznačne, postulirati da se u slučaju bilo kakvih neslaganja bira „najduža“ verzija operacije (tj. do sljedećeg skupa znakova koje čita prevodilac odgovara bilo kojoj operaciji, nastavlja da se čita), pokušajte da otkrijete kolizije tokom prevođenja i generišete greške u kontroverznim slučajevima... Na ovaj ili onaj način, jezici koji dozvoljavaju deklaraciju novih operacija rešavaju ove probleme.

Ne treba zaboraviti da za nove operacije postoji i pitanje određivanja asocijativnosti i prioriteta. Više ne postoji gotovo rješenje u obliku operacije standardnog jezika, i obično samo trebate podesiti ove parametre prema pravilima jezika. Na primjer, učinite sve nove operacije lijevo-asocijativnim i dajte im isti, fiksni, prioritet ili uvedite u jezik sredstva za specificiranje oba.

Preopterećenje i polimorfne varijable

Kada se preopterećeni operatori, funkcije i procedure koriste u jezicima jakog tipa, gdje svaka varijabla ima unaprijed deklarirani tip, na kompajleru je da odluči koju verziju preopterećenog operatora će koristiti u svakom konkretnom slučaju, bez obzira koliko složena . To znači da za kompajlirane jezike upotreba preopterećenja operatora ne dovodi do degradacije performansi – u svakom slučaju postoji dobro definirana operacija ili poziv funkcije u objektnom kodu programa. Drugačija je situacija kada je moguće koristiti polimorfne varijable u jeziku, odnosno varijable koje mogu sadržavati vrijednosti različitih tipova u različito vrijeme.

Pošto tip vrednosti na koju će se preopterećena operacija primeniti nije poznat u trenutku prevođenja koda, kompajler je lišen mogućnosti da unapred izabere pravu opciju. U ovom slučaju, prisiljen je ugraditi fragment u objektni kod koji će, neposredno prije izvođenja ove operacije, odrediti tipove vrijednosti u argumentima i dinamički odabrati varijantu koja odgovara ovom skupu tipova. Štaviše, takva definicija mora biti napravljena pri svakom izvršavanju operacije, jer čak i isti kod, koji se poziva po drugi put, može biti izveden drugačije.

Stoga, korištenje preopterećenja operatora u kombinaciji s polimorfnim varijablama čini neizbježnim dinamičko određivanje koda koji treba pozvati.

Kritika

Korištenje preopterećenja ne smatra se dobrom od strane svih stručnjaka. Ako preopterećenje funkcija i procedura općenito nije zamjerljivo (djelomično zato što ne dovodi do nekih tipičnih problema s "operatorom", dijelom zato što je manje primamljivo zloupotrijebiti ga), onda je preopterećenje operatora, u principu, , a u specifičnim jezičkim implementacijama, podvrgnut je prilično oštroj kritici mnogih teoretičara i praktičara programiranja.

Kritičari ističu da gore navedeni problemi identifikacije, prioriteta i asocijativnosti često čine rad s preopterećenim operatorima nepotrebno teškim ili neprirodnim:

  • Identifikacija. Ako jezik ima stroga pravila identifikacije, tada je programer primoran zapamtiti za koje kombinacije tipova postoje preopterećene operacije i ručno baciti operande na njih. Ako jezik dozvoljava "približnu" identifikaciju, nikada se ne može biti siguran da će u nekoj prilično komplikovanoj situaciji biti izvedena upravo ona varijanta operacije koju je programer imao na umu.
  • Prioritet i asocijativnost. Ako su oni strogo definirani, to može biti nezgodno i nije relevantno za predmetnu oblast (na primjer, za operacije sa skupovima, prioriteti se razlikuju od aritmetičkih). Ako ih programator može podesiti, to postaje dodatni izvor grešaka (makar samo zato što različite varijante jedne operacije imaju različite prioritete, pa čak i asocijativnost).

Koliko pogodnost korištenja vlastitih operacija može nadmašiti neugodnost pogoršanja upravljivosti programa je pitanje na koje nema jasan odgovor.

Sa stanovišta jezičke implementacije, isti problemi dovode do složenosti prevodilaca i smanjenja njihove efikasnosti i pouzdanosti. A upotreba preopterećenja u kombinaciji s polimorfnim varijablama je također očito sporija od pozivanja tvrdo kodirane operacije tokom kompilacije i pruža manje mogućnosti za optimizaciju objektnog koda. Specifičnosti implementacije preopterećenja na različitim jezicima podvrgnute su posebnoj kritici. Dakle, u C++, predmet kritike može biti nedostatak dogovora o internom predstavljanju imena preopterećenih funkcija, što dovodi do nekompatibilnosti na nivou biblioteka koje kompajliraju različiti C++ prevodioci.

Neki kritičari govore protiv operacija preopterećenja, zasnovanih na opštim principima teorije razvoja softvera i stvarne industrijske prakse.

  • Zagovornici "puritanskog" pristupa izgradnji jezika, kao što su Wirth ili Hoare, protive se preopterećenju operatera jednostavno zato što se lako može riješiti. Po njihovom mišljenju, takvi alati samo komplikuju jezik i prevodioca, a da ne pružaju dodatne funkcije koje odgovaraju ovoj komplikacijama. Po njihovom mišljenju, sama ideja stvaranja proširenja jezika usmjerenog na zadatke samo izgleda privlačno. U stvarnosti, upotreba alata za proširenje jezika čini program razumljivim samo njegovom autoru - onome koji je razvio ovo proširenje. Program postaje mnogo teži za razumevanje i analizu drugih programera, što otežava održavanje, modifikacije i razvoj tima.
  • Primjećuje se da sama mogućnost korištenja preopterećenja često igra provokativnu ulogu: programeri počinju da je koriste gdje god je to moguće, kao rezultat toga, alat dizajniran da pojednostavi i pojednostavi program postaje uzrok njegove komplikacije i konfuzije.
  • Preopterećeni operateri možda neće učiniti baš ono što se od njih očekuje, ovisno o njihovoj vrsti. Na primjer, a + b obično (ali ne uvijek) znači isto što i b + a , ali "jedan" + "dva" se razlikuje od "dva" + "jedan" na jezicima gdje je + operator preopterećen za konkatenacija nizova.
  • Preopterećenje operatora čini fragmente programa osjetljivijima na kontekst. Bez poznavanja tipova operanada uključenih u izraz, nemoguće je razumjeti šta izraz radi ako koristi preopterećene operatore. Na primjer, u C++ programu, izraz<< может означать и побитовый сдвиг, и вывод в поток. Выражение a << 1 возвращает результат побитового сдвига значения a на один бит влево, если a - целая переменная, но если a является выходным потоком , то же выражение выведет в этот поток строку «1» .

Klasifikacija

Slijedi klasifikacija nekih programskih jezika prema tome da li dozvoljavaju preopterećenje operatora i da li su operatori ograničeni na unaprijed definirani skup:

Operacije Nema preopterećenja Došlo je do preopterećenja
Ograničen skup operacija
  • Objective-C
  • Python
Moguće je definirati nove operacije
  • PostgreSQL
  • vidi takođe

    Wikimedia Foundation. 2010 .

    Pogledajte šta je "Preopterećenje funkcija" u drugim rječnicima:

      - (operatori, funkcije, procedure) u programiranju jedan od načina implementacije polimorfizma, koji se sastoji u mogućnosti istovremenog postojanja u jednom opsegu više različitih varijanti operacije (operator, funkcija ili ... ... Wikipedia



Kako postići preopterećenje funkcije u C? (10)

Postoji li način da se postigne preopterećenje funkcija u C-u? Gledam jednostavne funkcije koje mogu biti preopterećene kao

foo (int a) foo (char b) foo (float c, int d)

Mislim da ne postoji direktan način; Tražim rješenja, ako postoje.

Nadam se da će vam kod u nastavku pomoći da shvatite preopterećenje funkcija

#include #include int zabava (int a, ...); int main(int argc, char *argv)( fun(1,10); fun(2,"cquestionbank"); return 0; ) int fun(int a, ...)( va_list vl; va_start(vl,a ); if(a==1) printf("%d",va_arg(vl,int)); else printf("\n%s",va_arg(vl,char *)); )

Mislim, misliš - ne, ne možeš.

Funkciju va_arg možete deklarirati kao

void my_func(char* format, ...);

Ali moraćete da prosledite neke informacije o broju varijabli i njihovim tipovima u prvom argumentu - kao printf() .

Da, kao.

Ovdje daješ primjer:

void printA(int a)( printf("Zdravo svijet iz printA: %d\n",a); ) void printB(const char *buff)(printf("Zdravo svijet iz printB: %s\n",buff) ; ) #define Max_ITEMS() 6, 5, 4, 3, 2, 1, 0 #define __VA_ARG_N(_1, _2, _3, _4, _5, _6, N, ...) N #define _Broj_ARGS_(... ) __VA_ARG_N(__VA_ARGS__) #define NUM_ARGS(...) (_Num_ARGS_(_0, ## __VA_ARGS__, Max_ITEMS()) - 1) #define CHECK_ARGS_MAX_LIMIT(t) if(NUM_ARGS)(args) #define CHECK_ARGS(args) if(NUM_ARGS(args) #define print(x , args ...) \ CHECK_ARGS_MIN_LIMIT(1) printf("error");fflush(stdout); \ CHECK_ARGS_MAX_LIMIT(4) printf("error");fflush(stdout) ; \ (( \ if (__builtin_types_compatible_p (typeof (x), int)) \ printA(x, ##args); \ else \ printB (x,##args); \ )) int main(int argc, char* * argv) ( int a=0; print(a); print("zdravo"); return (EXIT_SUCCESS); )

Izaći će 0 i pozdrav iz printA i printB.

Ako je vaš kompajler gcc i nemate ništa protiv da radite ručno ažuriranje svaki put kada dodate novo preopterećenje, možete napraviti masu makroa i dobiti rezultat koji želite sa tačke gledišta pozivatelja, nije baš lijepo za pisanje... To je moguće

pogledajte __builtin_types_compatible_p, a zatim ga koristite da definirate makro koji radi nešto poput

#define foo(a) \ ((__builtin_types_compatible_p(int, a)?foo(a):(__builtin_types_compatible_p(float, a)?foo(a):)

ali da, gadno, samo ne

EDIT: C1X će dobiti podršku za izraze tipa, koji izgledaju ovako:

#define cbrt(X) _Generic((X), long double: cbrtl, \ default: cbrt, \ float: cbrtf)(X)

Kao što je već rečeno, C ne podržava preopterećenje u smislu na koji mislite. Uobičajeni idiom za rješavanje problema je da funkcija preuzme označenu uniju. Ovo se implementira pomoću parametra struct, gdje se sama struktura sastoji od neke vrste indikatora tipa, kao što je enum, i unije različitih tipova vrijednosti. primjer:

#include typedef enum ( T_INT, T_FLOAT, T_CHAR, ) my_type; typedef struct ( my_type type; union ( int a; float b; char c; ) my_union; ) my_struct; void set_overload (my_struct *whatever) ( switch (whatever->type) ( case T_INT: whatever->my_union.a = 1; break; case T_FLOAT: whatever->my_union.b = 2.0; break; case T_CHAR: whatever-> my_union.c = "3"; ) ) void printf_overload (my_struct *whatever) ( switch (whatever->type) ( case T_INT: printf("%d\n", whatever->my_union.a); break; case T_FLOAT : printf("%f\n", whatever->my_union.b); break; case T_CHAR: printf("%c\n", whatever->my_union.c); break; ) ) int main (int argc, char* argv) ( my_struct s; s.type=T_INT; set_overload(&s); printf_overload(&s); s.type=T_FLOAT; set_overload(&s); printf_overload(&s); s.type=T_CHAR; set_overload(&s) printf_overload(&s); )

Zar ne možete jednostavno koristiti C++ i ne koristiti sve druge C++ karakteristike osim ove?

Ako do sada nije postojao striktno strogi C, umjesto toga bih preporučio varijabilne funkcije.

Sljedeći pristup je sličan a2800276, ali sa nekim C99 makroima:

// trebamo `size_t` #include // tipovi argumenata za prihvatanje enuma sum_arg_types (SUM_LONG, SUM_ULONG, SUM_DOUBLE); // struktura koja drži argument struct sum_arg ( enum sum_arg_types type; union ( long as_long; unsigned long as_ulong; double as_double; ) value; ); // odredimo veličinu niza #define count(NIZ) ((sizeof (ARRAY))/(sizeof *(ARRAY))) // ovako će se naša funkcija zvati #define sum(...) _sum( count(sum_args(__VA_ARGS__)), sum_args(__VA_ARGS__)) // kreiraj niz `struct sum_arg` #define sum_args(...) ((struct sum_arg )( __VA_ARGS__ )) // kreiraj inicijalizatore za argumente su #delong (VRIJEDNOST) ( SUM_LONG, ( .as_long = (VALUE) ) ) #define sum_ulong(VALUE) ( SUM_ULONG, ( .as_ulong = (VALUE) ) ) #define sum_double(VALUE) ( SUM_DOUBLE, ( .as_double = (VALUE) ) ) // naša polimorfna funkcija long double _sum(size_t count, struct sum_arg * args) ( long double vrijednost = 0; for(size_t i = 0; i< count; ++i) { switch(args[i].type) { case SUM_LONG: value += args[i].value.as_long; break; case SUM_ULONG: value += args[i].value.as_ulong; break; case SUM_DOUBLE: value += args[i].value.as_double; break; } } return value; } // let"s see if it works #include int main() ( unsigned long foo = -1; duga dvostruka vrijednost = sum(sum_long(42), sum_ulong(foo), sum_double(1e10)); printf("%Le\n", vrijednost); vrati 0; )

Za sada, _Generic pošto je pitanje _Generic, standardni C (bez ekstenzija) je efektivno primljeno podrška za funkcije preopterećenja (a ne operatore) zahvaljujući dodavanju _Generic riječi _Generic u C11. (podržano u GCC-u od verzije 4.9)

(Preopterećenje nije zaista "ugrađeno" na način prikazan u pitanju, ali je lako uništiti nešto što ovako funkcionira.)

Generic je operator vremena kompajliranja u istoj porodici kao sizeof i _Alignof. Opisano je u standardnom odjeljku 6.5.1.1. Potrebna su dva glavna parametra: izraz (koji se neće evaluirati u vrijeme izvođenja) i lista asocijacija tipa/izraza, što je malo poput bloka prekidača. _Generic dobiva generički tip izraza, a zatim se "prebacuje" na njega kako bi odabrao konačni rezultat izraza na listi za njegov tip:

Generic(1, float: 2.0, char *: "2", int: 2, default: get_two_object());

Gornji izraz ima vrijednost 2 - tip kontrolnog izraza je int, tako da odabire izraz povezan s int kao vrijednost. Ništa od ovoga ne ostaje za vrijeme izvođenja. (Podrazumevana klauzula je obavezna: ako je ne navedete i tip se ne podudara, to će uzrokovati grešku kompilacije.)

Tehnika koja je korisna za preopterećenje funkcije je da je može umetnuti C predprocesor i odabrati rezultatski izraz na osnovu tipa argumenata koji se prosljeđuju kontrolnom makrou. Dakle (primjer iz C standarda):

#define cbrt(X) _Generic((X), \ long double: cbrtl, \ default: cbrt, \ float: cbrtf \)(X)

Ovaj makro implementira preopterećenu cbrt operaciju prosljeđivanjem tipa argumenta makrou, odabirom odgovarajuće implementacijske funkcije, a zatim prosljeđivanjem originalnog makroa toj funkciji.

Dakle, da implementiramo vaš originalni primjer, mogli bismo učiniti sljedeće:

Foo_int (int a) foo_char (char b) foo_float_int (float c , int d) #define foo(_1, ...) _Generic((_1), \ int: foo_int, \ char: foo_char, \ float: _Generic(( FIRST(__VA_ARGS__,)), \int: foo_float_int))(_1, __VA_ARGS__) #define FIRST(A, ...) A

U ovom slučaju, mogli bismo koristiti zadano: vezivanje za treći slučaj, ali to ne pokazuje kako proširiti princip na više argumenata. Krajnji rezultat je da možete koristiti foo(...) u svom kodu bez brige (mnogo) o vrsti vaših argumenata.

Za složenije situacije, kao što su funkcije koje preopterećuju više argumenata ili mijenjaju brojeve, možete koristiti uslužne makroe za automatsko generiranje statičkih struktura za otpremu:

void print_ii(int a, int b) ( printf("int, int\n"); ) void print_di(double a, int b) ( printf("double, int\n"); ) void print_iii(int a, int b, int c) ( printf("int, int, int\n"); ) void print_default(void) ( printf("nepoznati argumenti\n"); ) #define print(...) OVERLOAD(print, (__VA_ARGS__), \ (print_ii, (int, int)), \ (print_di, (double, int)), \ (print_iii, (int, int, int)) \) #define OVERLOAD_ARG_TYPES (int, double) #define OVERLOAD_FUNCTIONS (print) #include "activate-overloads.h" int main(void) ( print(44, 47); // ispisuje "int, int" print(4.4, 47); // ispisuje "double, int" print (1, 2, 3); // ispisuje "int, int, int" print(""); // ispisuje "nepoznate argumente" )

(implementacija ovdje). Uz malo truda, možete smanjiti šablon da izgleda prilično slično jeziku sa ugrađenom podrškom za preopterećenje.

Na stranu, već je bilo moguće preopteretiti količina argumenti (a ne tip) u C99.

Imajte na umu da vas način na koji se procjenjuje C može pokrenuti. Ovo će odabrati foo_int ako mu pokušate proslijediti literalni karakter, na primjer, i potreban vam je neki foo_int ako želite da vaša preopterećenja podržavaju literale niza. Međutim, generalno prilično cool.

Leušenkov odgovor je stvarno kul: samo foo primjer se ne kompajlira sa GCC-om, koji ne uspijeva na foo(7) , nailazeći na FIRST makro i stvarni poziv funkcije ((_1, __VA_ARGS__) , ostajući sa dodatnim zarezom. Također, nailazimo na probleme ako želimo pružiti dodatna preopterećenja kao što je foo(double) .

Zato sam odlučio da odgovorim na ovo pitanje detaljnije, uključujući dopuštanje praznog preopterećenja (foo(void) - što je izazvalo neke probleme...).

Ideja je sada: definisati više od jednog generičkog u različitim makroima i neka ispravan bude izabran prema broju argumenata!

Broj argumenata je prilično jednostavan, na osnovu ovog odgovora:

#define foo(...) SELECT(__VA_ARGS__)(__VA_ARGS__) #define SELECT(...) CONCAT(SELECT_, NARG(__VA_ARGS__))(__VA_ARGS__) #define CONCAT(X, Y) CONCAT_(X, Y) # definiraj CONCAT_(X, Y) X ## Y

To je dobro, odlučujemo ili za SELECT_1 ili SELECT_2 (ili više argumenata ako ih želite/trebate), tako da nam trebaju samo odgovarajuće definicije:

#define SELECT_0() foo_void #define SELECT_1(_1) _Generic ((_1), \ int: foo_int, \ char: foo_char, \ double: foo_double \) #define SELECT_2(_1, _2) _Generic((_1), \ double : _Generic((_2), \ int: foo_double_int \) \)

Prvo, prazan poziv makroa (foo()) i dalje stvara token, ali je prazan. Dakle, makro za brojanje zapravo vraća 1 umjesto 0, čak i ako je makro nazvan prazan. Ovaj problem možemo "lako" riješiti ako __VA_ARGS__ sa zarezom iza __VA_ARGS__ uslovno, u zavisnosti od toga da li je lista prazna ili ne:

#define NARG(...) ARG4_(__VA_ARGS__ COMMA(__VA_ARGS__) 4, 3, 2, 1, 0)

Ovo pogledao lako, ali COMMA makro je prilično težak; na sreću, ova tema je već obrađena na blogu Jensa Gustedta (hvala, Jens). Glavni trik je da se makroi funkcije ne proširuju osim ako ih prate zagrade, pogledajte Jensov blog za dalje objašnjenje... Samo trebamo malo modificirati makroe za naše potrebe (koristit ću kraća imena i manje argumenata radi kratkoće) .

#define ARGN(...) ARGN_(__VA_ARGS__) #define ARGN_(_0, _1, _2, _3, N, ...) N #define HAS_COMMA(...) ARGN(__VA_ARGS__, 1, 1, 1, 0 ) #define SET_COMMA(...) , #define COMMA(...) SELECT_COMMA \ (\ HAS_COMMA(__VA_ARGS__), \ HAS_COMMA(__VA_ARGS__ ()), \ HAS_COMMA(SET_COMMA __VA_ARGS__), \ HAS_COMMA_SET_VA_COM_COMMA_SET \) #define SELECT_COMMA(_0, _1, _2, _3) SELECT_COMMA_(_0, _1, _2, _3) #define SELECT_COMMA_(_0, _1, _2, _3) COMMA_ ## _0 ## _1 #_3 #2 ## definiraj COMMA_0000 , #define COMMA_0001 #define COMMA_0010 , // ... (svi ostali sa zarezom) #define COMMA_1111 ,

I sad smo dobro...

Cijeli kod u jednom bloku:

/* * demo.c * * Napravljeno: 14.09.2017 * Autor: sboehler */ #include void foo_void(void) ( puts("void"); ) void foo_int(int c) ( printf("int: %d\n", c); ) void foo_char(char c) ( printf("char: %c \n", c); ) void foo_double(double c) ( printf("double: %.2f\n", c); ) void foo_double_int(double c, int d) ( printf("double: %.2f, int: %d\n", c, d); ) #define foo(...) SELECT(__VA_ARGS__)(__VA_ARGS__) #define SELECT(...) CONCAT(SELECT_, NARG(__VA_ARGS__))(__VA_ARGS__) # define CONCAT(X, Y) CONCAT_(X, Y) #define CONCAT_(X, Y) X ## Y #define SELECT_0() foo_void #define SELECT_1(_1) _Generic ((_1), \ int: foo_int, \ char : foo_char, \ double: foo_double \) #define SELECT_2(_1, _2) _Generic((_1), \ double: _Generic((_2), \ int: foo_double_int \) \) #define ARGN(...) ARGN_( __VA_ARGS__) #define ARGN_(_0, _1, _2, N, ...) N #define NARG(...) ARGN(__VA_ARGS__ COMMA(__VA_ARGS__) 3, 2, 1, 0) #define HAS_COMMA(...) ARGN(__VA_ARGS__, 1, 1, 0) #define SET_COMMA(...) , #define COMMA(...) SELECT_COMMA \ (\ HAS_COMMA(__VA_ARGS__), \ HAS_COMMA(__VA_ARGS__ ()), \ HAS_COMMA_SET_VA_ , \ HAS_COMMA(SET_COMMA __VA_ARGS__ ()) \) #define SELECT_COMMA(_0, _1, _2, _3) SELECT_COMMA_(_0, _1, _2, _3) #define SELECT_COMMA_(_0, _1, _0) # COMMA _0 # _1 ## _2 ## _Define Comma_0010, #define zaremo_0100, #define comma_0100, #define comma_0110, #define comma_0111, #define comma_1000, #define comma_1001, #define comma_1010 , #define COMMA_1011 , #define COMMA_1100 , #define COMMA_1101 , #define COMMA_1110 , #define COMMA_1111 , int main(int argc, char** argv) ( foo(); foo(7); foo(10.12); foo(12.10, 7); foo((char)"s"); return 0; )

C++ vam omogućava da navedete više od jedne definicije za funkcije ime ili operater u istoj oblasti kao funkcija preopterećenja I preopterećenja operatera respektivno.

Preopterećena deklaracija je deklaracija deklarirana pod istim imenom kao i prethodno deklarirana deklaracija u istom opsegu, osim što obje deklaracije imaju različite argumente i očigledno različitu definiciju (implementaciju).

Kada zovete preopterećenog funkcija ili operater, prevodilac određuje najprikladniju definiciju za korištenje uspoređujući tipove argumenata koje ste koristili za pozivanje funkcije ili operatora s tipovima parametara navedenim u definicijama. Poziva se proces odabira najprikladnije preopterećene funkcije ili operatora rezolucija preopterećenja .

Preopterećenje funkcija u C++

Možete imati više definicija za isto ime funkcije u istom opsegu. Definicija funkcije se mora razlikovati jedna od druge u smislu tipova i/ili broja argumenata u listi argumenata. Ne možete preopteretiti deklaracije funkcije koje se razlikuju samo po svom tipu povratka.

Ispod je primjer gdje je ista funkcija print() koristi se za štampanje različitih vrsta podataka -

#include korištenje imenskog prostora std; klasa printData ( public: void print(int i) ( cout<< "Printing int: " << i << endl; } void print(double f) { cout << "Printing float: " << f << endl; } void print(char* c) { cout << "Printing character: " << c << endl; } }; int main(void) { printData pd; // Call print to print integer pd.print(5); // Call print to print float pd.print(500.263); // Call print to print character pd.print("Hello C++"); return 0; }

Int. štampe: 5 Ispis float: 500.263 Znak za štampu: Zdravo C++

Preopterećenje operatora u C++

Možete nadjačati ili preopteretiti većinu ugrađenih operatora dostupnih u C++. Stoga programer može koristiti i operatore sa korisnički definiranim tipovima.

Preopterećeni operatori su funkcije sa posebnim imenima: ključna riječ "operator" praćena znakom za operatora koji se definira. Kao i svaka druga funkcija, preopterećeni operator ima tip povratka i listu parametara.

Box operator+(const Box&);

deklarira operator dodavanja koji se može koristiti dopune dva Box objekta i vraća konačni Box objekt. Većina preopterećenih operatora može se definirati kao obične funkcije koje nisu članice ili kao funkcije članice klase. U slučaju da definiramo gornju funkciju kao funkciju člana ne-klase, morali bismo proslijediti dva argumenta za svaki operand na sljedeći način:

Box operator+(const Box&, const Box&);

Ispod je primjer koji pokazuje koncept operatora kada se učita pomoću funkcije člana. Ovdje se objekt prosljeđuje kao argument čijim će se svojstvima pristupiti pomoću ovog objekta, objektu koji će pozvati ovaj operator može se pristupiti pomoću ovo operater kao što je opisano u nastavku -

#include korištenje imenskog prostora std; class Box ( public: double getVolume(void) (povratna dužina * širina * visina; ) void setLength(double len) (dužina = len; ) void setBreadth(double bre) ( širina = bre; ) void setHeight(double hei) ( visina = hei; ) // Preopterećenje + operator za dodavanje dva objekta Box.Box operator+(const Box& b) ( Box box; box.length = this->length + b.length; box.breadth = this->breadth + b .breadth; box.height = this->height + b.height; return box; ) private: dvostruka dužina; // Dužina kutije dvostruka širina; // Širina kutije dvostruka visina; // Visina kutije ) ; // Glavna funkcija za program int main() ( Box Box1; // Deklariraj Box1 tipa Box Box2; // Deklariši Box2 tipa Box Box Box3; // Deklariši Box3 tipa Box dvostruki volumen = 0.0; // Store volumen kutije ovdje // specifikacija kutije 1 Box1.setLength(6.0); Box1.setBreadth(7.0); Box1.setHeight(5.0); // specifikacija kutije 2 Box2.setLength(12.0); ;Box2.setHeight(10.0 ); // volumen kutije 1 volumen = Box1.getVolume(); cout<< "Volume of Box1: " << volume <

Kada se gornji kod kompajlira i izvrši, proizvodi sljedeći izlaz:

Volumen kutije 1: 210 Volumen kutije 2: 1560 Volumen kutije 3: 5400

Overloadable / Non-overloadableOperators

Ispod je lista operatora koji mogu biti preopterećeni.



Nastavak teme:
Windows

Natalya Komarova , 28.05.2009. (25.03.2018.) Kada čitate forum ili blog, sjećate se autora postova po nadimku i ... po slici korisnika, tzv avataru ....