Konstruktor w C++ to specjalna metoda, która jest wywoływana automatycznie w momencie tworzenia obiektu. Służy ogólnie do inicjowania elementów danych nowych obiektów. Konstruktor w C++ ma taką samą nazwę jak klasa lub struktura. Konstruuje wartości, tj. dostarcza dane dla obiektu, dlatego nazywa się go konstruktorem.
- Konstruktor jest funkcją składową klasy, której nazwa jest taka sama jak nazwa klasy.
- Konstruktor to specjalny typ funkcji składowej, który służy do automatycznego inicjowania elementów danych obiektu klasy, gdy tworzony jest obiekt tej samej klasy.
- Konstruktor jest wywoływany w momencie tworzenia obiektu. Konstruuje wartości, tj. dostarcza dane dla obiektu, dlatego nazywa się go konstruktorem.
- Konstruktory nie zwracają wartości, dlatego nie mają typu zwracanego.
- Konstruktor jest wywoływany automatycznie, gdy tworzymy obiekt klasy.
- Konstruktory mogą być przeciążone.
- Konstruktora nie można zadeklarować jako wirtualnego.
Składnia konstruktorów w C++
Prototyp konstruktora wygląda następująco:
(list-of-parameters);>
Konstruktor można zdefiniować wewnątrz deklaracji klasy lub poza deklaracją klasy
Składnia definiowania konstruktora w klasie
(list-of-parameters) { // constructor definition }> Składnia definiowania konstruktora poza klasą
: :(list-of-parameters) { // constructor definition }> Przykłady konstruktorów w C++
Poniższe przykłady pokazują, jak zadeklarować konstruktory dla klasy w C++:
Przykład 1: Definiowanie konstruktora w klasie
C++
// defining the constructor within the class> #include> using> namespace> std;> class> student {> >int> rno;> >char> name[50];> >double> fee;> public>:> >// constructor> >student()> >{> >cout <<>'Enter the RollNo:'>;> >cin>>nie;> >cout <<>'Enter the Name:'>;> >cin>> imię;> >cout <<>'Enter the Fee:'>;> >cin>> opłata;> >}> >void> display()> >{> >cout << endl << rno <<>' '> << name <<>' '> << fee;> >}> };> int> main()> {> >student s;>// constructor gets called automatically when> >// we create the object of the class> >s.display();> >return> 0;> }> |
>
>
Wyjście
Enter the RollNo:121 Enter the Name:Geeks Enter the Fee:5000 121 Geeks 5000>
Przykład 2: Definiowanie konstruktora poza klasą
C++
// defining the constructor outside the class> #include> using> namespace> std;> class> student {> >int> rno;> >char> name[50];> >double> fee;> public>:> >// constructor declaration only> >student();> >void> display();> };> // outside definition of constructor> student::student()> {> >cout <<>'Enter the RollNo:'>;> >cin>>nie;> >cout <<>'Enter the Name:'>;> >cin>> imię;> >cout <<>'Enter the Fee:'>;> >cin>> opłata;> }> void> student::display()> {> >cout << endl << rno <<>' '> << name <<>' '> << fee;> }> // driver code> int> main()> {> >student s;> >s.display();> >return> 0;> }> |
>
>
Wyjście
Enter the RollNo:11 Enter the Name:Aman Enter the Fee:10111 11 Aman 10111>
Notatka: Możemy zdefiniować konstruktor poza klasą jako wbudowane aby uczynić ją równoważną definicji in class. Ale zauważ to wbudowane nie jest instrukcją dla kompilatora, jest to jedynie żądanie, które kompilator może wdrożyć lub nie, w zależności od okoliczności.
Charakterystyka konstruktorów w C++
Poniżej przedstawiono kilka głównych cech konstruktorów w C++:
- Nazwa konstruktora jest taka sama jak nazwa jego klasy.
- Konstruktory są najczęściej deklarowane w publicznej części klasy, chociaż można je zadeklarować w prywatnej części klasy.
- Konstruktory nie zwracają wartości; dlatego nie mają typu zwracanego.
- Konstruktor jest wywoływany automatycznie, gdy tworzymy obiekt klasy.
- Konstruktory mogą być przeciążone.
- Konstruktora nie można zadeklarować jako wirtualnego.
- Konstruktora nie można dziedziczyć.
- Nie można odwoływać się do adresów Konstruktora.
- Konstruktor wykonuje niejawne wywołania metody nowy I usuwać operatory podczas alokacji pamięci.
Rodzaje konstruktorów w C++
Konstruktory można klasyfikować na podstawie sytuacji, w których są używane. W C++ istnieją 4 typy konstruktorów:
- Domyślny konstruktor
- Konstruktor parametryczny
- Kopiuj konstruktor
- Przenieś konstruktora
Przyjrzyjmy się typom konstruktorów w C++ na przykładzie z życia wziętego. Załóżmy, że poszedłeś do sklepu, aby kupić marker. Kiedy chcesz kupić marker, jakie masz opcje? Najpierw idziesz do sklepu i mówisz daj mi marker. Zatem samo powiedzenie „daj mi marker” oznacza, że nie określiłeś nazwy marki i koloru, nie wspomniałeś o niczym, po prostu powiedziałeś, że chcesz marker. Kiedy więc powiedzieliśmy, że chcę tylko marker, niezależnie od tego, jaki często sprzedawany marker jest dostępny na rynku lub w jego sklepie, po prostu go przekaże. I tym właśnie jest domyślny konstruktor!
Druga metoda polega na tym, że idziesz do sklepu i mówisz, że chcę marker w kolorze czerwonym i markę XYZ. Więc wspominasz o tym, a on da ci ten znacznik. Zatem w tym przypadku podałeś parametry. I tym właśnie jest sparametryzowany konstruktor!
Potem za trzecim idziesz do sklepu i mówisz, że chcę taki marker (fizyczny marker na dłoni). Zatem sprzedawca zobaczy ten znacznik. OK, a on da ci nowy znacznik. Więc skopiuj ten znacznik. I tym właśnie jest konstruktor kopiujący!
Załóżmy teraz, że nie chcesz kupować nowego znacznika, ale zamiast tego przejmujesz na własność znacznik swojego przyjaciela. Oznacza to przejęcie na własność już istniejących zasobów zamiast zdobywania nowych. Tym właśnie jest konstruktor ruchu!
1. Domyślny konstruktor w C++
A domyślny konstruktor jest konstruktorem, który nie przyjmuje żadnych argumentów. Nie ma żadnych parametrów. Nazywa się go także konstruktorem bezargumentowym.
Składnia domyślnego konstruktora
className() { // body_of_constructor }> Przykłady konstruktora domyślnego
Poniższe przykłady pokazują, jak używać domyślnych konstruktorów w C++.
Przykład 1:
CPP
// C++ program to illustrate the concept of default> // constructors> #include> using> namespace> std;> class> construct {> public>:> >int> a, b;> >// Default Constructor> >construct()> >{> >a = 10;> >b = 20;> >}> };> int> main()> {> >// Default constructor called automatically> >// when the object is created> >construct c;> >cout <<>'a: '> << c.a << endl <<>'b: '> << c.b;> >return> 1;> }> |
>
>Wyjście
a: 10 b: 20>
Notatka: Nawet jeśli nie zdefiniujemy jawnie żadnego konstruktora, kompilator automatycznie domyślnie udostępni konstruktor domyślny.
Przykład 2:
C++
// C++ program to demonstrate the implicit default> // constructor> #include> using> namespace> std;> // class> class> student {> >int> rno;> >char> name[50];> >double> fee;> public>:> };> int> main()> {> >// creating object without any parameters> >student s;> >return> 0;> }> |
>
>
Wyjście
(no output)>
Jak widzimy, jesteśmy w stanie utworzyć obiekt klasy student bez przekazywania żadnych argumentów, nawet jeśli nie zdefiniowaliśmy dla niego żadnego jawnego konstruktora domyślnego.
2. Konstruktor parametryczny w C++
Konstruktory sparametryzowane umożliwiają przekazywanie argumentów konstruktorom. Zazwyczaj te argumenty pomagają zainicjować obiekt podczas jego tworzenia. Aby utworzyć sparametryzowany konstruktor, po prostu dodaj do niego parametry w taki sam sposób, jak do każdej innej funkcji. Kiedy definiujesz treść konstruktora, użyj parametrów, aby zainicjować obiekt.
indeks górny w ilustratorze
Składnia konstruktora parametrycznego
className (parameters...) { // body }> Przykłady konstruktora parametrycznego
Poniższe przykłady pokazują, jak używać sparametryzowanych konstruktorów w C++.
Przykład 1: Definiowanie sparametryzowanego konstruktora wewnątrz klasy.
CPP
// CPP program to illustrate parameterized constructors> #include> using> namespace> std;> class> Point {> private>:> >int> x, y;> public>:> >// Parameterized Constructor> >Point(>int> x1,>int> y1)> >{> >x = x1;> >y = y1;> >}> >int> getX() {>return> x; }> >int> getY() {>return> y; }> };> int> main()> {> >// Constructor called> >Point p1(10, 15);> >// Access values assigned by constructor> >cout <<>'p1.x = '> << p1.getX()> ><<>', p1.y = '> << p1.getY();> >return> 0;> }> |
>
>Wyjście
p1.x = 10, p1.y = 15>
Przykład 2: Definiowanie konstruktora parametrycznego poza klasą.
C++
// C++ Program to illustrate how to define the parameterized> // constructor outside the class> #include> #include> using> namespace> std;> // class definition> class> student {> >int> rno;> >char> name[50];> >double> fee;> public>:> >student(>int>,>char>[],>double>);> >void> display();> };> // parameterized constructor outside class> student::student(>int> no,>char> n[],>double> f)> {> >rno = no;> >strcpy>(name, n);> >fee = f;> }> void> student::display()> {> >cout << endl << rno <<>' '> << name <<>' '> << fee;> }> // driver code> int> main()> {> >student s(1001,>'Ram'>, 10000);> >s.display();> >return> 0;> }> |
>
>Wyjście
1001 Ram 10000>
Kiedy obiekt jest zadeklarowany w sparametryzowanym konstruktorze, wartości początkowe muszą zostać przekazane jako argumenty do funkcji konstruktora. Zwykły sposób deklaracji obiektu może nie działać. Sparametryzowane konstruktory można wywoływać jawnie lub niejawnie:
Example e = Example(0, 50); // Explicit call Example e(0, 50); // Implicit call>
Gdy zdefiniowany jest konstruktor sparametryzowany i nie jest jawnie zdefiniowany żaden konstruktor domyślny, kompilator nie utworzy domyślnie konstruktora domyślnego, a tym samym nie utworzy prostego obiektu w postaci:
Student s;>
wyświetli błąd.
Przykład 3:
C++
// C++ Program to illustrate the error caused be not> // defining the explicit defualt constructor after> // parameterized constructor> #include> #include> using> namespace> std;> // class definition> class> student {> >int> rno;> >char> name[50];> >double> fee;> public>:> >student(>int> no,>char> n[],>double> f)> >{> >rno = no;> >strcpy>(name, n);> >fee = f;> >}> };> // driver code> int> main()> {> >student s;>// this will cause error> >return> 0;> }> |
>
>
Wyjście
main.cpp: In function ‘int main()’: main.cpp:25:13: error: no matching function for call to ‘student::student()’ 25 | student s; // this will cause error | ^ main.cpp:14:5: note: candidate: ‘student::student(int, char*, double)’ 14 | student(int no, char n[], double f) | ^~~~~~~ main.cpp:14:5: note: candidate expects 3 arguments, 0 provided main.cpp:8:7: note: candidate: ‘constexpr student::student(const student&)’ 8 | class student { | ^~~~~~~ main.cpp:8:7: note: candidate expects 1 argument, 0 provided main.cpp:8:7: note: candidate: ‘constexpr student::student(student&&)’ main.cpp:8:7: note: candidate expects 1 argument, 0 provided ^~> Ważna uwaga: Ilekroć definiujemy jeden lub więcej konstruktorów innych niż domyślne (z parametrami) dla klasy, konstruktor domyślny (bez parametrów) powinien być również jawnie zdefiniowany, ponieważ kompilator nie udostępni w tym przypadku konstruktora domyślnego. Nie jest to jednak konieczne, ale najlepszą praktyką jest zawsze definiowanie konstruktora domyślnego.
Zastosowania konstruktora parametrycznego
- Służy do inicjowania różnych elementów danych różnych obiektów różnymi wartościami podczas ich tworzenia.
- Służy do przeciążania konstruktorów.
Domyślne argumenty z konstruktorem sparametryzowanym C++
Podobnie jak w przypadku normalnych funkcji, możemy również zdefiniować domyślne wartości argumentów sparametryzowanych konstruktorów. Wszystkie zasady domyślne argumenty zostaną zastosowane do tych parametrów.
Przykład 3: Definiowanie sparametryzowanego konstruktora z wartościami domyślnymi
C++
// C++ Program to illustrate how to use default arguments> // with parameterized constructor> #include> using> namespace> std;> // class> class> GFG {> private>:> >int> data;> public>:> >// parameterized constructor with default values> >GFG(>int> x = 0) { data = x; }> >int> getData() {>return> data; }> };> int> main()> {> >GFG obj1;>// will not throw error> >GFG obj2(25);> >cout <<>'First Object Data: '> << obj1.getData() << endl;> >cout <<>'Second Object Data: '> << obj2.getData()> ><< endl;> >return> 0;> }> |
>
>Wyjście
First Object Data: 0 Second Object Data: 25>
Jak widzimy, gdy każdemu argumentowi sparametryzowanego konstruktora przypisane są wartości domyślne, dopuszczalne jest utworzenie obiektu bez przekazywania jakichkolwiek parametrów, tak jak w przypadku konstruktorów domyślnych. Zatem ten typ konstruktora działa zarówno jako konstruktor domyślny, jak i sparametryzowany.
3. Kopiuj konstruktor w C++
Konstruktor kopiujący to funkcja członkowska, która inicjuje obiekt przy użyciu innego obiektu tej samej klasy.
Składnia Kopiuj konstruktor
Kopiuj konstruktor przyjmuje jako argument referencję do obiektu tej samej klasy.
ClassName (ClassName &obj) { // body_containing_logic }> Podobnie jak konstruktor domyślny, kompilator C++ udostępnia również niejawny konstruktor kopiujący, jeśli nie ma jawnej definicji konstruktora kopiującego. W tym miejscu należy zauważyć, że w przeciwieństwie do domyślnego konstruktora, w którym obecność dowolnego typu jawnego konstruktora powoduje usunięcie ukrytego konstruktora domyślnego, niejawny konstruktor kopiujący będzie zawsze tworzony przez kompilator, jeśli nie ma jawnego konstruktora kopiującego lub obecny jest jawny konstruktor przenoszenia.
Przykłady konstruktora kopiującego
Poniższe przykłady pokazują, jak używać konstruktorów kopiujących w C++.
Przykład 1: Ilustracja niejawnego konstruktora kopiującego
C++
// C++ program to illustrate the use of Implicit copy> // constructor> #include> using> namespace> std;> class> Sample {> >int> id;> public>:> >// parameterized constructor> >Sample(>int> x) { id = x; }> >void> display() { cout <<>'ID='> << id; }> };> int> main()> {> >Sample obj1(10);> >obj1.display();> >cout << endl;> >// creating an object of type Sample from the obj> >Sample obj2(obj1);>// or obj2=obj1;> >obj2.display();> >return> 0;> }> |
>
>Wyjście
ID=10 ID=10>
Przykład 2: Definiowanie jawnego konstruktora kopiującego
C++
// C++ Program to demonstrate how to define the explicit> // copy constructor> #include> using> namespace> std;> class> Sample {> >int> id;> public>:> >// default constructor with empty body> >Sample() {}> >// parameterized constructor> >Sample(>int> x) { id = x; }> >// copy constructor> >Sample(Sample& t) { id = t.id; }> >void> display() { cout <<>'ID='> << id; }> };> // driver code> int> main()> {> >Sample obj1(10);> >obj1.display();> >cout << endl;> >// copy constructor called> >Sample obj2(obj1);>// or obj2=obj1;> >obj2.display();> >return> 0;> }> |
>
lista użytkowników mysql
>Wyjście
ID=10 ID=10>
Przykład 3: Definiowanie jawnego konstruktora kopiującego za pomocą konstruktora parametrycznego
C++
// C++ program to demonstrate copy construction along with> // parameterized constructor> #include> #include> using> namespace> std;> // class definition> class> student {> >int> rno;> >char> name[50];> >double> fee;> public>:> >student(>int>,>char>[],>double>);> >student(student& t)>// copy constructor> >{> >rno = t.rno;> >strcpy>(name, t.name);> >fee = t.fee;> >}> >void> display();> };> student::student(>int> no,>char> n[],>double> f)> {> >rno = no;> >strcpy>(name, n);> >fee = f;> }> void> student::display()> {> >cout << endl << rno <<>' '> << name <<>' '> << fee;> }> int> main()> {> >student s(1001,>'Manjeet'>, 10000);> >s.display();> >student manjeet(s);>// copy constructor called> >manjeet.display();> >return> 0;> }> |
>
>Wyjście
1001 Manjeet 10000 1001 Manjeet 10000>
Zastosowanie konstruktora kopiującego
- Konstruuje nowy obiekt, kopiując wartości z istniejącego obiektu.
- Można go używać do wykonywania głębokiego kopiowania.
- W razie potrzeby zmodyfikuj określone atrybuty podczas procesu kopiowania.
4. Przenieś konstruktor w C++
Konstruktor przenoszenia jest najnowszym dodatkiem do rodziny konstruktorów w C++. Działa to jak konstruktor kopiujący, który konstruuje obiekt z już istniejących obiektów, ale zamiast kopiować obiekt do nowej pamięci, wykorzystuje semantykę przenoszenia, aby przenieść własność już utworzonego obiektu na nowy obiekt bez tworzenia dodatkowych kopie.
Można to postrzegać jako kradzież zasobów z innych obiektów.
Składnia konstruktora przenoszenia w C++
className (className&& obj) { // body of the constructor }> The konstruktor przenoszenia bierze odniesienie do wartości obiektu tej samej klasy i przenosi własność tego obiektu na nowo utworzony obiekt.
Podobnie jak konstruktor kopiujący, kompilator utworzy konstruktor przenoszenia dla każdej klasy, która nie ma żadnego jawnego konstruktora przenoszenia.
Przykłady konstruktora przenoszenia
Poniższe przykłady pokazują, jak używać konstruktorów przenoszenia w C++.
Przykład 1: Definiowanie konstruktora przenoszenia
C++
// C++ Program to illustrate how to define a move> // constructor> #include> using> namespace> std;> class> Box {> public>:> >int>* data;>// Pointer to an integer value> >// Constructor> >Box(>int> value)> >{> >data =>new> int>;> >*data = value;> >}> >// Move constructor> >Box(Box&& other) noexcept> >{> >cout <<>'Move Constructor Called'> << endl;> >data = other.data;>// Transfer ownership of 'other'> >// data> >other.data = nullptr;>// Null out 'other' to prevent> >// double deletion> >}> >// Destructor> >~Box() {>delete> data; }> };> int> main()> {> >// Create a Box with value 42> >Box originalBox(42);> >// Create a new Box by moving resources from the> >// originalBox> >Box newBox(move(originalBox));> >cout <<>'newBox.data: '> << *newBox.data;> >// originalBox is now in a valid but unspecified> >// state (its resources were moved to newBox)> >return> 0;> }> |
>
>Wyjście
Move Constructor Called newBox.data: 42>
Zastosowanie konstruktora przenoszenia
- Zamiast tworzyć kopie, konstruktory przenoszenia skutecznie przenoszą własność tych zasobów.
- Zapobiega to niepotrzebnemu kopiowaniu pamięci i zmniejsza obciążenie.
- Możesz zdefiniować własnego konstruktora przenoszenia do obsługi określonych transferów zasobów.
Destruktory w C++
Destruktor jest także specjalną funkcją członkowską pełniącą funkcję konstruktora. Destruktor niszczy obiekty klas utworzone przez konstruktora. Destructor ma taką samą nazwę jak nazwa klasy poprzedzona symbolem tyldy (~). Nie jest możliwe zdefiniowanie więcej niż jednego destruktora. Destruktor to tylko jeden ze sposobów zniszczenia obiektu utworzonego przez konstruktora. Dlatego destruktor nie może być przeciążony. Destruktor nie wymaga żadnego argumentu ani nie zwraca żadnej wartości. Jest wywoływana automatycznie, gdy obiekt wykracza poza zakres. Destruktory zwalniają przestrzeń pamięci zajmowaną przez obiekty utworzone przez konstruktora. W niszczyciel , obiekty ulegają zniszczeniu w odwrotności procesu tworzenia obiektu.
Składnia destruktorów w C++
Podobnie jak konstruktory, destruktory można również definiować wewnątrz lub na zewnątrz klasy.
Składnia definiowania destruktora w klasie
~ (){}> Składnia definiowania destruktora poza klasą
: : ~(){}> Przykłady destruktorów w C++
Poniższe przykłady pokazują, jak używać destruktorów w C++.
Przykład 1: Definiowanie prostego destruktora
C++
#include> using> namespace> std;> class> Test {> public>:> >Test() { cout <<>'
Constructor executed'>; }> >~Test() { cout <<>'
Destructor executed'>; }> };> main()> {> >Test t;> >return> 0;> }> |
>
>Wyjście
Constructor executed Destructor executed>
Przykład 2: Liczenie, ile razy obiekt został utworzony i zniszczony
C++
// C++ Program to count the number of objects created and> // destroyed> #include> using> namespace> std;> // global variable to count> int> count = 0;> // class definition> class> Test {> public>:> >Test()> >{> >count++;> >cout <<>'No. of Object created: '> << count << endl;> >}> >~Test()> >{> >cout <<>'No. of Object destroyed: '> << count> ><< endl;> >--count;> >}> };> // driver code> int> main()> {> >Test t, t1, t2, t3;> >return> 0;> }> |
>
>
Wyjście
No. of Object created: 1 No. of Object created: 2 No. of Object created: 3 No. of Object created: 4 No. of Object destroyed: 4 No. of Object destroyed: 3 No. of Object destroyed: 2 No. of Object destroyed: 1>
Charakterystyka destruktorów w C++
Poniżej przedstawiono kilka głównych cech destruktorów w C++:
- Destruktor jest wywoływany automatycznie przez kompilator, gdy odpowiadający mu konstruktor wykracza poza zakres i zwalnia przestrzeń pamięci, która nie jest już wymagana przez program.
- Destruktor nie wymaga żadnych argumentów ani nie zwraca żadnej wartości, dlatego nie można go przeciążać.
- Destruktora nie można zadeklarować jako statycznego ani stałego;
- Destruktor należy zadeklarować w publicznej części programu.
- Destruktor wywoływany jest w kolejności odwrotnej do wywołania konstruktora.
Często zadawane pytania dotyczące konstruktorów C++
Jakie funkcje są domyślnie generowane przez kompilator, jeśli nie udostępnimy ich jawnie?
Funkcje, które domyślnie są generowane przez kompilator, jeśli nie podajemy ich jawnie, to:
- Domyślny konstruktor
- Kopiuj konstruktor
- Przenieś konstruktory
- Operator przypisania
- Niszczyciel
Czy możemy uczynić konstruktorów prywatnymi?
Tak, w C++ konstruktory można ustawić jako prywatne. Oznacza to, że żaden kod zewnętrzny nie może bezpośrednio utworzyć obiektu tej klasy.
Czym konstruktory różnią się od normalnej funkcji członkowskiej?
Konstruktor różni się od normalnych funkcji pod następującymi względami:
- Konstruktor ma taką samą nazwę jak sama klasa
- Konstruktory domyślne nie mają argumentów wejściowych, jednak konstruktory kopiujące i sparametryzowane mają argumenty wejściowe
- Konstruktory nie mają typu zwracanego
- Konstruktor jest wywoływany automatycznie podczas tworzenia obiektu.
- Należy go umieścić w publicznej części zajęć.
- Jeśli nie określimy konstruktora, kompilator C++ wygeneruje domyślny konstruktor dla obiektu (nie oczekuje żadnych parametrów i ma pustą treść).
Czy w klasie można mieć więcej niż jednego konstruktora?
Tak, w klasie możemy mieć więcej niż jednego konstruktora. Nazywa się to Przeciążenie konstruktora .
Powiązane artykuły:
- Destruktory w C++
- Quiz na temat konstruktorów w C++
- Dane wyjściowe programów C++ | Zestaw 26 (Konstruktorzy)
- Dane wyjściowe programów C++ | Zestaw 27 (konstruktory i destruktory)