Menu
Coddy logo textTech

Stałe funkcje składowe

Część sekcji Programowanie obiektowe ścieżki C++ w Coddy. Lekcja 29 z 104.

W poprzedniej lekcji widziałeś słowo kluczowe const przy metodach pobierających. Ale co dokładnie oznacza, gdy const pojawia się po liście parametrów funkcji? Stała funkcja składowa gwarantuje, że nie zmodyfikuje żadnych zmiennych składowych obiektu.

class Rectangle {
    int width;
    int height;
public:
    Rectangle(int w, int h) : width(w), height(h) {}
    
    int getArea() const {      // funkcja składowa const
        return width * height;  // Odczytywanie pól jest dozwolone
    }
    
    void setWidth(int w) {     // Nie-const — modyfikuje obiekt
        width = w;
    }
};

const po liście parametrów informuje kompilator: „Ta funkcja nie zmieni stanu obiektu”. Jeśli spróbujesz zmodyfikować zmienną składową wewnątrz funkcji const, kompilator zgłosi błąd.

Staje się to niezbędne podczas pracy z obiektami const lub referencjami const. Obiekt const może wywoływać tylko funkcje składowe const:

void printArea(const Rectangle& rect) {
    std::cout << rect.getArea();    // OK - getArea() jest const
    // rect.setWidth(10);           // ERROR - setWidth() nie jest const
}

Oznaczanie funkcji jako const, gdy nie modyfikują obiektu, jest dobrą praktyką. Dokumentuje Twoje intencje, umożliwia działanie funkcji na obiektach const i pomaga kompilatorowi wykrywać przypadkowe modyfikacje. Każda funkcja składowa, która tylko odczytuje dane, powinna być oznaczona jako const.

challenge icon

Wyzwanie

Łatwy

Zbudujmy konwerter temperatur, który pokaże, kiedy i dlaczego używać metod składowych oznaczonych jako const. Utworzysz klasę, której niektóre metody tylko odczytują dane (i powinny być oznaczone jako const), a inne modyfikują stan obiektu.

Utworzysz dwa pliki, aby uporządkować kod:

  • Temperature.h: Zdefiniuj klasę Temperature, która przechowuje wartość temperatury i udostępnia różne sposoby jej odczytu i modyfikowania. Twoja klasa powinna zawierać:
    • Prywatne pole celsius (double) do przechowywania temperatury
    • Konstruktor przyjmujący początkową wartość w stopniach Celsjusza
    • Metodę getCelsius(), która zwraca przechowywaną wartość. Powinna być oznaczona jako const, ponieważ tylko odczytuje dane
    • Metodę getFahrenheit(), która oblicza i zwraca temperaturę w stopniach Fahrenheita, używając wzoru celsius * 9.0 / 5.0 + 32.0; ona również powinna być oznaczona jako const, ponieważ niczego nie modyfikuje
    • Metodę getKelvin(), która zwraca temperaturę w kelwinach, używając celsius + 273.15; ona także powinna być oznaczona jako const
    • Metodę setCelsius(double value), która aktualizuje przechowywaną temperaturę. Nie może być oznaczona jako const, ponieważ modyfikuje obiekt
    • Metodę adjustBy(double delta), która dodaje wartość delta do bieżącej temperatury; ona również nie powinna być oznaczona jako const
  • main.cpp: Pokaż, jak działają metody składowe oznaczone jako const zarówno ze zwykłymi, jak i stałymi obiektami. Odczytaj początkową wartość temperatury z wejścia, a następnie:
    • Utwórz obiekt Temperature z podaną wartością
    • Wypisz "Initial: <celsius>C = <fahrenheit>F = <kelvin>K"
    • Zwiększ temperaturę o 10.0 stopni
    • Wypisz "After adjustment: <celsius>C"
    • Utwórz funkcję pomocniczą void printReadings(const Temperature& temp), która przyjmuje stałą referencję i wypisuje "Reading: <celsius>C, <fahrenheit>F". Ta funkcja może wywoływać dla temp tylko metody oznaczone jako const
    • Wywołaj printReadings() dla swojego obiektu temperatury
    • Ustaw temperaturę na 0.0 (punkt zamarzania)
    • Wypisz "Freezing point: <celsius>C = <fahrenheit>F"

Formatuj wszystkie wartości temperatury do jednego miejsca po przecinku, używając std::fixed i std::setprecision(1) z <iomanip>.

Najważniejsze jest to, że printReadings() otrzymuje stałą referencję, więc może wywoływać tylko metody oznaczone jako const. Dlatego ważne jest prawidłowe oznaczenie metod pobierających dane jako const. Dzięki temu mogą działać w kontekstach, w których obiektu nie można modyfikować.

Spróbuj swoich sił

#include <iostream>
#include <iomanip>
#include "Temperature.h"
using namespace std;

// TODO: Zaimplementuj tutaj metody klasy Temperature
// Konstruktor
Temperature::Temperature(double initialCelsius) {
    // TODO: Zainicjalizuj celsius
}

// TODO: Zaimplementuj getCelsius() jako const

// TODO: Zaimplementuj getFahrenheit() jako const

// TODO: Zaimplementuj getKelvin() jako const

// TODO: Zaimplementuj setCelsius(double value)

// TODO: Zaimplementuj adjustBy(double delta)


// TODO: Utwórz funkcję pomocniczą printReadings, która przyjmuje const Temperature& 
// i wypisuje "Reading: <celsius>C, <fahrenheit>F"
// Uwaga: Ta funkcja może wywoływać na temp tylko metody const!


int main() {
    double initialTemp;
    cin >> initialTemp;

    // Ustaw formatowanie wyjścia
    cout << fixed << setprecision(1);

    // TODO: Utwórz obiekt Temperature z wartością wejściową

    // TODO: Wypisz "Initial: <celsius>C = <fahrenheit>F = <kelvin>K"

    // TODO: Zmień temperaturę o 10.0 stopni

    // TODO: Wypisz "After adjustment: <celsius>C"

    // TODO: Wywołaj printReadings() z utworzonym obiektem Temperature

    // TODO: Ustaw temperaturę na 0.0 (punkt zamarzania)

    // TODO: Wypisz "Freezing point: <celsius>C = <fahrenheit>F"

    return 0;
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator C++ online