Konstruktor domyślny
Część sekcji Programowanie obiektowe ścieżki C++ w Coddy. Lekcja 18 z 104.
Konstruktor domyślny to konstruktor, który można wywołać bez argumentów. Inicjalizuje obiekt, gdy nie podano wartości początkowych. Każda klasa musi umożliwiać tworzenie obiektów w prawidłowym stanie domyślnym.
Jeśli nie zdefiniujesz żadnego konstruktora, kompilator wygeneruje niejawny konstruktor domyślny, który nic nie robi w przypadku typów prymitywnych i wywołuje konstruktory domyślne dla obiektów składowych.
class Player {
int health;
int score;
public:
Player() { // Konstruktor domyślny
health = 100;
score = 0;
}
};
Player p1; // Wywołuje konstruktor domyślny
Player p2{}; // Również wywołuje konstruktor domyślnyGdy zdefiniujesz dowolny konstruktor (na przykład konstruktor z parametrami), kompilator nie będzie już generować konstruktora domyślnego. Jeśli nadal go potrzebujesz, musisz jawnie go zdefiniować.
class Enemy {
int damage;
public:
Enemy(int d) : damage(d) {} // Tylko konstruktor z parametrem
};
Enemy e1(10); // Działa
Enemy e2; // Błąd! Brak konstruktora domyślnegoWe współczesnym C++ możesz jawnie zażądać konstruktora domyślnego generowanego przez kompilator za pomocą = default:
class Item {
int id;
public:
Item() = default; // Kompilator generuje konstruktor domyślny
Item(int i) : id(i) {}
};Konstruktory domyślne są niezbędne do tworzenia tablic obiektów oraz dla klas używanych w kontenerach takich jak std::vector, które mogą wymagać tworzenia elementów bez argumentów.
Wyzwanie
ŁatwyStwórzmy prosty system liczników, który pokazuje, jak konstruktory domyślne inicjalizują obiekty w prawidłowym stanie początkowym.
Utworzysz dwa pliki, aby uporządkować swój kod:
Counter.h: Zdefiniuj klasęCounter, która przechowuje wartość licznika. Twoja klasa powinna mieć:- Prywatny atrybut
count(liczba całkowita) - Prywatny atrybut
name(ciąg znaków) służący do identyfikacji licznika - Konstruktor domyślny, który inicjalizuje
countwartością0, anamewartością"Unnamed", a następnie wyświetla"Counter created: <name>" - Metodę
increment(), która zwiększa licznik o 1 - Metodę
getCount(), która zwraca bieżącą wartość licznika - Metodę
getName(), która zwraca nazwę licznika
- Prywatny atrybut
main.cpp: Pokaż, że konstruktory domyślne działają przy tworzeniu obiektów na różne sposoby. Odczytaj z wejścia liczbę określającą, ile razy zwiększyć licznik, a następnie:- Utwórz obiekt Counter za pomocą inicjalizacji bezpośredniej:
Counter c1; - Utwórz kolejny obiekt Counter za pomocą inicjalizacji nawiasami klamrowymi:
Counter c2{}; - Zwiększaj wartość
c1tyle razy, ile podano na wejściu - Wyświetl
"<name>: <count>"dla c1 - Wyświetl
"<name>: <count>"dla c2
- Utwórz obiekt Counter za pomocą inicjalizacji bezpośredniej:
Dzięki konstruktorowi domyślnemu oba liczniki powinny zaczynać od 0, ale zwiększana będzie wartość tylko c1. Pokazuje to, jak konstruktory domyślne zapewniają, że każdy obiekt rozpoczyna działanie w przewidywalnym, prawidłowym stanie, niezależnie od sposobu jego utworzenia.
Dołącz plik nagłówkowy w main.cpp za pomocą #include "Counter.h".
Spróbuj swoich sił
#include <iostream>
#include "Counter.h"
using namespace std;
int main() {
// Odczytaj liczbę inkrementacji
int n;
cin >> n;
// TODO: Utwórz obiekt Counter przy użyciu inicjalizacji bezpośredniej: Counter c1;
// TODO: Utwórz kolejny obiekt Counter przy użyciu inicjalizacji nawiasami klamrowymi: Counter c2{};
// TODO: Zwiększ wartość c1 tyle razy, ile wskazuje n
// TODO: Wypisz "<name>: <count>" dla c1
// TODO: Wypisz "<name>: <count>" dla c2
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