Przeciążanie operatorów arytmetycznych
Część sekcji Programowanie obiektowe ścieżki C++ w Coddy. Lekcja 41 z 104.
Operatory arytmetyczne, takie jak +, -, * i /, są często przeciążane, aby klasy niestandardowe zachowywały się jak wbudowane typy numeryczne. Operatory te zazwyczaj zwracają nowy obiekt, zamiast modyfikować operandy.
Oto klasa Fraction z operatorami arytmetycznymi:
class Fraction {
int numerator, denominator;
public:
Fraction(int n, int d) : numerator(n), denominator(d) {}
Fraction operator+(const Fraction& other) const {
return Fraction(
numerator * other.denominator + other.numerator * denominator,
denominator * other.denominator
);
}
Fraction operator*(const Fraction& other) const {
return Fraction(numerator * other.numerator,
denominator * other.denominator);
}
};Zauważ, że oba operatory są oznaczone jako const, ponieważ nie modyfikują żadnego z operandów. Tworzą nowy obiekt Fraction z wynikiem i go zwracają.
W przypadku operatorów przypisania złożonego, takich jak +=, wzorzec jest inny. Modyfikują one lewy operand i zwracają do niego referencję:
Fraction& operator+=(const Fraction& other) {
numerator = numerator * other.denominator + other.numerator * denominator;
denominator = denominator * other.denominator;
return *this;
}Częstą praktyką jest implementowanie podstawowego operatora za pomocą operatora przypisania złożonego, co ogranicza duplikację kodu:
Fraction operator+(const Fraction& other) const {
Fraction result = *this; // Skopiuj ten obiekt
result += other; // Użyj przypisania złożonego
return result;
}To podejście zapewnia spójność obu operatorów i ułatwia konserwację.
Wyzwanie
ŁatwyStwórzmy klasę Money, która obsługuje obliczenia walutowe za pomocą przeciążania operatorów arytmetycznych. Zaimplementujesz kilka operatorów arytmetycznych, które pozwolą Ci operować na wartościach pieniężnych równie naturalnie jak na zwykłych liczbach.
Utworzysz dwa pliki, aby uporządkować swój kod:
Money.h: Zdefiniuj klasęMoney, która przechowuje kwotę w centach (jakoint), aby uniknąć problemów z precyzją liczb zmiennoprzecinkowych. Klasa powinna obsługiwać:- Konstruktor, który przyjmuje dolary i centy jako osobne liczby całkowite
- Getter
getDollars(), który zwraca część kwoty wyrażoną w dolarach - Getter
getCents(), który zwraca część kwoty wyrażoną w centach (0-99) - Przeciążone operatory
+i-, które zwracają nowy obiektMoney - Przeciążone operatory przypisania złożonego
+=i-=, które modyfikują bieżący obiekt i zwracają do niego referencję - Metodę
display(), która wyświetla kwotę w formacie$X.YY(centy zawsze jako dwie cyfry)
Zaimplementuj podstawowe operatory (
+i-) za pomocą operatorów przypisania złożonego, aby ograniczyć powielanie kodu, tak jak pokazano w lekcji. Wszystkie operatory arytmetyczne powinny być oznaczone jakoconsttam, gdzie to właściwe.main.cpp: Odczytaj z wejścia cztery liczby całkowite reprezentujące dwie kwoty pieniężne (dollars1, cents1, dollars2, cents2 w osobnych wierszach). Utwórz dwa obiektyMoney, a następnie zademonstruj działanie wszystkich operatorów:- Wyświetl
"Amount 1: ", a następnie pierwszą kwotę - Wyświetl
"Amount 2: ", a następnie drugą kwotę - Dodaj obie kwoty i wyświetl
"Sum: ", a następnie wynik - Odejmij drugą kwotę od pierwszej i wyświetl
"Difference: ", a następnie wynik - Użyj
+=, aby dodać drugą kwotę do pierwszej, a następnie wyświetl"After +=: ", a po nim zmodyfikowaną pierwszą kwotę
- Wyświetl
W metodzie display() użyj std::setw(2) i std::setfill('0') z <iomanip>, aby centy były zawsze wyświetlane jako dwie cyfry (np. $5.07, a nie $5.7).
Konwertuj ciągi wejściowe na liczby całkowite za pomocą std::stoi(). Nie zapomnij o strażnikach nagłówka w pliku nagłówkowym.
Spróbuj swoich sił
#include <iostream>
#include <string>
#include "Money.h"
using namespace std;
int main() {
// Wczytaj dane dla dwóch kwot
string line;
getline(cin, line);
int dollars1 = stoi(line);
getline(cin, line);
int cents1 = stoi(line);
getline(cin, line);
int dollars2 = stoi(line);
getline(cin, line);
int cents2 = stoi(line);
// TODO: Utwórz dwa obiekty Money z wartościami wejściowymi
// TODO: Wypisz "Amount 1: ", a następnie wyświetl pierwszą kwotę
// TODO: Wypisz "Amount 2: ", a następnie wyświetl drugą kwotę
// TODO: Dodaj obie kwoty i wypisz "Sum: ", a następnie wynik
// TODO: Odejmij drugą kwotę od pierwszej i wypisz "Difference: ", a następnie wynik
// TODO: Użyj +=, aby dodać drugą kwotę do pierwszej, a następnie wypisz "After +=: " i zmodyfikowaną pierwszą kwotę
return 0;
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneBudowanie i kompilacja C++Pliki nagłówkowe i pliki źródłowePrzestrzenie nazw i zakresWprowadzenie do programowania obiektowego w C++Klasy a obiektyWskaźnik „this”Metody (funkcje składowe)Atrybuty (składowe danych)Podstawy konstruktorów i destruktorówPowtórzenie – prosty kalkulator4Właściwości klas
Elementy instancji a elementy statyczneGettery i setteryStałe funkcje składoweSłowo kluczowe mutableMetody i zmienne statyczneFunkcje i klasy zaprzyjaźnionePodsumowanie – menedżer konta bankowego7Dziedziczenie
Podstawy dziedziczeniaPoziomy dostępu w dziedziczeniuKolejność wywołań konstruktora i destruktoraNadpisywanie metodFunkcje wirtualne i VTableWielokrotne dziedziczenieDziedziczenie wirtualnePowtórzenie — hierarchia pracowników2Zarządzanie pamięcią
Pamięć stosu a stertyWskaźniki i referencjePamięć dynamiczna (new/delete)Inteligentne wskaźniki w C++RAII w C++Podsumowanie — menedżer tablicy dynamicznej5Hermetyzacja
Specyfikatory dostępu w C++Specyfikatory dostępu — szczegółowoUkrywanie informacjiStruktura a klasaKlasy zagnieżdżone i wewnętrznePodsumowanie — system ewidencji studentów8Polimorfizm
Polimorfizm czasu kompilacji i wykonaniaPrzeciążanie funkcjiFunkcje wirtualne — powtórkaCzysto wirtualne funkcjeKlasy abstrakcyjneProjektowanie interfejsów w C++Rzutowanie dynamiczne i RTTIPodsumowanie — kalkulator kształtów3Konstruktory i destruktory
Konstruktor domyślnyKonstruktor z parametramiKonstruktor kopiującyKonstruktor przenoszącyListy inicjalizacyjne konstruktoraKonstruktory delegująceDestruktor — szczegółowe omówienieZasada trzech / pięciu / zeraPodsumowanie — klasa String6Przeciążanie operatorów
Wprowadzenie do przeciążania operatorówPrzeciążanie operatorów arytmetycznychPrzeciążanie operatorów porównaniaOperatory strumieniowePrzeciążanie operatora przypisaniaPrzeciążanie operatorów [] i ()Operatory konwersji typówPodsumowanie — klasa Matrix9Szablony
Szablony funkcjiSzablony klasSpecjalizacja szablonówSzablony wariadycznePodstawy SFINAE i cech typówPodsumowanie — kontener generycznyPoćwicz samodzielnie: Kompilator C++ online