Operatory arytmetyczne są zwykle używane do operacji arytmetycznych. Czy nie jest miło mieć +, połącz dwie struny?? Włączenie tego jest uważane za przeciążenie operatora dodawania arytmetycznego dla łańcuchów.
Operator inkrementacji, ++ dodaje 1 do int lub float. Kiedy mamy do czynienia ze wskaźnikami, nie dodaje 1 do wskaźnika. Sprawia, że wskaźnik wskazuje na następny kolejny obiekt w pamięci. Iterator wskazuje następny obiekt na połączonej liście, ale obiekty połączonej listy znajdują się w różnych miejscach w pamięci (nie w kolejnych regionach). Czy nie byłoby miło przeciążyć operatora inkrementacji dla iteratora, aby inkrementować, ale wskazywać na następujący element na połączonej liście?
Ten artykuł wyjaśnia przeciążanie w C++. Jest podzielony na dwie części: przeciążanie funkcji i przeciążanie operatora. Znajomość podstaw C++ jest niezbędna do zrozumienia dalszej części artykułu.
Treść artykułu
- Przeciążenie funkcji
- Przeciążenie operatora
- Przykładowe przeciążenie operatora klasy ciągu
- Przeciążenie operatora iteratora
- Wniosek
Przeciążenie funkcji
Poniższa funkcja dodaje dwie wartości typu int i zwraca wartość typu int:
int add(int no1, int no2)suma int = nr1 + nr2;
suma zwrotu;
Prototyp tej funkcji to:
int add(int nr1, int nr2);
Prototyp funkcji w nagłówku funkcji, zakończony średnikiem. Poniższa funkcja o tej samej nazwie, ale z innym prototypem, doda trzy liczby zmiennoprzecinkowe i zwróci liczbę zmiennoprzecinkową:
float add(float no1, float no2, float no3)
suma zmiennoprzecinkowa = nie1 + nie2 + nie3;
suma zwrotu;
W jaki sposób kompilator rozróżnia, którą funkcję należy wywołać, skoro dwie lub więcej funkcji ma tę samą nazwę?? Kompilator używa liczby argumentów i typów argumentów, aby określić, którą funkcję wywołać. Lista parametrów przeciążonych funkcji powinna różnić się liczbą i/lub typami parametrów. Tak więc wywołanie funkcji,
int sm = dodaj(2, 3);wywoła funkcję całkowitą, podczas gdy funkcja wywoła,
pływak sme = dodaj(2.3, 3.4, 2.0);wywołałby funkcję zmiennoprzecinkową. Uwaga: są sytuacje, w których kompilator odrzuci przeciążoną funkcję, gdy liczba argumentów jest taka sama, ale różnych typów! - Powód: - patrz później.
Poniższy program uruchamia powyższe segmenty kodu:
#zawieraćprzy użyciu standardowej przestrzeni nazw;
int add(int no1, int no2)
suma int = nr1 + nr2;
suma zwrotu;
float add(float no1, float no2, float no3)
suma zmiennoprzecinkowa = nie1 + nie2 + nie3;
suma zwrotu;
int main()
int sm = dodaj(2, 3);
Cout<
Cout<
Dane wyjściowe to:
5
7.7
Przeciążenie operatora
Operatory arytmetyczne służą do przeciążania operacji w typach klas. Iterator jest typem klasy. Operatory inkrementacji i dekrementacji służą do przeciążania operacji dla iteratora.
Przykładowe przeciążenie operatora klasy ciągu
W tej sekcji przedstawiono przykład, w którym + jest przeciążony dla prostej zaprojektowanej klasy łańcucha, zwanej klasą sprężyny. + łączy literały dwóch obiektów napisowych, zwracając nowy obiekt z połączonymi literałami. Łączenie dwóch literałów oznacza łączenie drugiego literału z końcem pierwszego literału.
Teraz C++ ma specjalną funkcję składową dla wszystkich klas, zwaną operatorem. Programista może użyć tej specjalnej funkcji do przeciążenia operatorów, takich jak +. Poniższy program pokazuje przeciążenie operatora + dla dwóch ciągów.
#zawieraćprzy użyciu standardowej przestrzeni nazw;
klasa wiosna
publiczny:
//członkowie danych
wartość char[100];
intn;
char concat[100];
//funkcje członków
wiosna (znak arr[])
dla (int i=0; i<100; ++i)
wart[i] = przyp[i];
if (arr[i] == '\0')
złamać;
wew;
dla (i=0; i<100; ++i) if (arr[i] == '\0') break;
n = i;
operator sprężyny+(sprężyna i st)
int newLen = n + st.n;
char nowaStr[nowaDł+1];
dla (int i=0; i
wiosna obj(newStr);
zwróć obj;
;
int main()
char ch1[] = "Nienawidzę cię! "; sprężyna str1(ch1);
char ch2[] = "Ale ona cię kocha!"; sprężyna str2(ch2);
znak ch3[] = "jeden"; sprężyna str3(ch3);
słowo3 = słowo1 + słowo2;
Cout<
Wartość str1 to „Nienawidzę cię! ". Wartość str2 to „Ale ona cię kocha!". Wartość str3, czyli str1 + str2, jest wynikiem:
"Nienawidzę cię! Ale ona cię kocha!"
czyli konkatenacja dwóch literałów napisowych. Same ciągi są obiektami skonkretyzowanymi.
Definicja funkcji operatora znajduje się w opisie (definicji) klasy string. Zaczyna się od typu zwracanego, „spring” dla „string”. Specjalna nazwa „operator, podążaj za tym”. Po nim jest symbol operatora (do przeciążenia). Następnie jest lista parametrów, która w rzeczywistości jest listą operandów. + jest operatorem binarnym: co oznacza, że przyjmuje lewy i prawy operand. Jednak według specyfikacji C++ lista parametrów tutaj ma tylko właściwy parametr only. Następnie jest ciało funkcji operatora, która naśladuje zachowanie zwykłego operatora.
Zgodnie ze specyfikacją C++, definicja operatora + przyjmuje tylko prawy parametr operandu, ponieważ reszta opisu klasy to lewy parametr operandu.
W powyższym kodzie tylko definicja funkcji operator+() dotyczy + przeciążania. Reszta kodu dla klasy to normalne kodowanie. Wewnątrz tej definicji dwa literały ciągu są połączone w tablicę newStr[]. Następnie tworzony jest nowy obiekt tekstowy (instancja) przy użyciu argumentu newStr[]. Na końcu definicji funkcji operator+() zwracany jest nowo utworzony obiekt, posiadający połączony ciąg znaków.
W funkcji main() dodawanie odbywa się za pomocą instrukcji:
słowo3 = słowo1 + słowo2;Gdzie str1, str2 i str3 to obiekty łańcuchowe, które zostały już utworzone w main(). Wyrażenie „str1 + str2” z jego + wywołuje funkcję członkowską operator+() w obiekcie str11. Funkcja członkowska operator+() w obiekcie str1 używa str2 jako argumentu i zwraca nowy obiekt z (opracowanym) połączonym ciągiem. Operator przypisania (=) kompletnej instrukcji zastępuje zawartość (wartości zmiennych) obiektu str3 tymi z zwracanego obiektu. W funkcji main() po dodaniu wartość składowej danych str3.val nie jest już „jeden”; jest to połączony (dodawanie) ciąg „Nienawidzę cię! Ale ona cię kocha!". Funkcja członkowska operator+() w obiekcie str1, używa literału ciągu własnego obiektu i literału ciągu swojego argumentu str2 w celu uzyskania połączonego literału ciągu.
Przeciążenie operatora iteratora
Kiedy mamy do czynienia z iteratorem, zaangażowane są co najmniej dwa obiekty: lista połączona i sam iterator. W rzeczywistości zaangażowane są co najmniej dwie klasy: klasa, z której tworzona jest lista połączona, oraz klasa, z której tworzony jest instancja iteratora.
Połączona lista
Diagram dla podwójnie połączonego obiektu listy to:
Ta lista składa się z trzech elementów, ale może być ich więcej. Trzy elementy tutaj są elementami liczb całkowitych. Pierwsza ma wartość 14; następny ma wartość 88; a ostatni ma wartość 47. Każdy element tutaj składa się z trzech następujących po sobie lokacji.
W przeciwieństwie do tablicy, w której każdy element jest jedną lokalizacją, a wszystkie elementy tablicy znajdują się w kolejnych lokalizacjach. Tutaj różne elementy znajdują się w różnych miejscach w serii pamięci, ale każdy element składa się z trzech następujących po sobie miejsc.
Dla każdego elementu środkowa lokalizacja zawiera wartość. Właściwa lokalizacja ma wskaźnik do następnego elementu. Lewa lokalizacja ma wskaźnik do poprzedniego elementu. W przypadku ostatniego elementu właściwa lokalizacja wskazuje na teoretyczny koniec listy. Dla pierwszego elementu lewa lokalizacja wskazuje na teoretyczny początek listy.
W przypadku tablicy operator inkrementacji (++) zwiększa wskaźnik, aby wskazywał na fizycznie następną lokalizację. Z listą elementy nie znajdują się w kolejnych regionach pamięci. Tak więc operator inkrementacji może być przeciążony, przesunąć iterator (wskaźnik) z jednego elementu na logicznie następny element. Ta sama projekcja dotyczy operatora dekrementacji (-).
Iterator do przodu to iterator, który po włączeniu wskazuje następny element. Iterator odwrotny to iterator, który po włączeniu wskazuje na poprzedni element.
Przeciążenie ++ ad -
Przeciążanie tych operatorów odbywa się w opisie klasy (definicji) iteratora.
Składnia prototypu przeciążenia operatora inkrementacji, prefiks, to
Operator ReturnType++();Składnia prototypu przeciążania operatora przyrostu, postfix, to
Operator ReturnType++(int);Składnia prototypu przeciążenia operatora dekrementacji, prefiks, to
Operator ReturnType--();Składnia prototypu przeciążania operatora przyrostu, postfix, to
Operator ReturnType--(int);Wniosek
Przeciążenie oznacza nadanie innego znaczenia funkcji lub operatorowi. Funkcje są przeciążone w tym samym zakresie. Tym, co odróżnia przeciążone funkcje, jest liczba i/lub typy parametrów na ich listach parametrów. W niektórych przypadkach, gdy liczba parametrów jest taka sama, ale przy różnych typach, kompilator odrzuca przeciążenie - patrz dalej. Wiele zwykłych operatorów może być przeciążonych w klasach, z których tworzone są obiekty. Odbywa się to poprzez podanie typu zwracanego, listy parametrów i treści do funkcji specjalnej o nazwie operator w opisie klasy.