Specyfikatory dostępu w C++
Część sekcji Programowanie obiektowe ścieżki C++ w Coddy. Lekcja 34 z 104.
C++ udostępnia trzy specyfikatory dostępu, które określają, kto może uzyskiwać dostęp do składowych klasy: public, protected i private. Stanowią one podstawę enkapsulacji.
class Account {
public:
std::string ownerName; // Dostępne z dowolnego miejsca
protected:
double interestRate; // Dostępne w tej klasie i klasach pochodnych
private:
double balance; // Dostępne tylko w obrębie tej klasy
};Członkami publicznymi można się posługiwać z dowolnego miejsca — wewnątrz klasy, w klasach pochodnych oraz z kodu zewnętrznego. Członkowie prywatni są najbardziej ograniczeni — dostęp do nich jest możliwy tylko w obrębie samej klasy. Chronione członkowie zajmują pośrednie miejsce — z zewnątrz działają jak prywatne, ale klasy pochodne mogą uzyskać do nich dostęp.
class Account {
private:
double balance;
public:
Account() : balance(0) {}
void deposit(double amount) {
balance += amount; // OK - wewnątrz klasy
}
};
int main() {
Account acc;
acc.deposit(100); // OK - deposit jest publiczna
// acc.balance = 500; // ERROR - balance jest prywatne
}Domyślnie wszystkie składowe klasy są prywatne, jeśli nie podano specyfikatora. Zachęca to do jawnego decydowania, co powinno być udostępniane. Zazwyczaj składowe danych są prywatne, a do bezpiecznej interakcji z nimi służą metody publiczne.
Wyzwanie
ŁatwyStwórzmy prosty system zarządzania pracownikami, który pokazuje, jak specyfikatory dostępu kontrolują, kto może uzyskać dostęp do poszczególnych elementów. Utworzysz klasę, w której część danych będzie całkowicie prywatna, część dostępna dla potencjalnych klas pochodnych, a część otwarta dla wszystkich.
Utworzysz dwa pliki, aby uporządkować swój kod:
Employee.h: Zdefiniuj klasęEmployee, która używa wszystkich trzech specyfikatorów dostępu do odpowiedniej ochrony danych:- Public:
name(string) pracownika. Można uzyskać do niego dostęp z dowolnego miejsca - Protected:
department(string) pracownika: dostępny wewnątrz klasy i dla klas pochodnych, ale nie z zewnątrz - Private:
salary(double) pracownika: dostępny wyłącznie wewnątrz samej klasy - Konstruktor, który przyjmuje nazwę, dział i wynagrodzenie, aby zainicjować wszystkie trzy składowe
- Publiczna metoda
getSalary(), która zwraca prywatną wartość wynagrodzenia - Publiczna metoda
getDepartment(), która zwraca chronioną wartość działu - Publiczna metoda
giveRaise(double amount), która zwiększa wynagrodzenie o podaną kwotę (tylko jeśli amount jest dodatnie) - Publiczna metoda
displayInfo(), która wyświetla informacje o pracowniku w formacie:"Name: <name>, Department: <department>, Salary: $<salary>"
- Public:
main.cpp: Zademonstruj działanie specyfikatorów dostępu, korzystając z obiektu Employee. Wczytaj z wejścia imię i nazwisko pracownika, dział oraz wynagrodzenie (trzy osobne wiersze), a następnie:- Utwórz obiekt
Employeez wczytanymi wartościami - Wyświetl imię i nazwisko pracownika bezpośrednio, uzyskując dostęp do publicznej składowej:
"Direct access - Name: <name>" - Wyświetl dział, korzystając z metody pobierającej:
"Via getter - Department: <department>" - Wyświetl wynagrodzenie, korzystając z metody pobierającej:
"Via getter - Salary: $<salary>" - Podnieś wynagrodzenie pracownika o
5000.0 - Wyświetl
"After raise:" - Wywołaj
displayInfo(), aby wyświetlić zaktualizowane informacje
- Utwórz obiekt
Formatuj wszystkie wartości wynagrodzenia z dokładnością do dwóch miejsc po przecinku, używając std::fixed i std::setprecision(2) z <iomanip>. Przekonwertuj wczytane wynagrodzenie z ciągu znaków na liczbę typu double za pomocą std::stod().
Najważniejsze jest to, że chociaż możesz uzyskać bezpośredni dostęp do name z main, nie możesz uzyskać bezpośredniego dostępu do department ani salary. Musisz korzystać z publicznych metod pobierających. To enkapsulacja w praktyce: klasa kontroluje sposób dostępu do swoich danych i ich modyfikowania.
Spróbuj swoich sił
#include <iostream>
#include <string>
#include <iomanip>
#include "Employee.h"
using namespace std;
int main() {
// Odczytaj dane wejściowe
string name;
string department;
string salaryStr;
getline(cin, name);
getline(cin, department);
getline(cin, salaryStr);
double salary = stod(salaryStr);
// Ustaw precyzję wyświetlania wynagrodzenia
cout << fixed << setprecision(2);
// TODO: Utwórz obiekt Employee z wartościami wejściowymi
// TODO: Wyświetl imię pracownika, uzyskując bezpośredni dostęp do publicznego pola
// Format: "Direct access - Name: <name>"
// TODO: Wyświetl dział za pomocą metody pobierającej
// Format: "Via getter - Department: <department>"
// TODO: Wyświetl wynagrodzenie za pomocą metody pobierającej
// Format: "Via getter - Salary: $<salary>"
// TODO: Przyznaj pracownikowi podwyżkę w wysokości 5000.0
// TODO: Wyświetl "After raise:"
// TODO: Wywołaj displayInfo(), aby wyświetlić zaktualizowane informacje
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