object-oriented constructor (tsz. object-oriented constructors)
A konstruktor egy osztály speciális tagfüggvénye, amely: - Ugyanolyan nevű, mint az osztály, és - Nincs visszatérési értéke (még void
sem).
Példa konstruktorra:
#include <iostream>
using namespace std;
class Auto {
public:
string marka;
// Konstruktor
Auto() {
marka = "Ismeretlen";
cout << "Konstruktor meghívva!" << endl;
}
};
int main() {
Auto a1; // Konstruktor automatikusan lefut
cout << "Márka: " << a1.marka << endl;
return 0;
}
Konstruktor meghívva! Márka: Ismeretlen
Amikor az Auto
osztályból létrehozunk egy a1
objektumot, a konstruktor automatikusan lefut.
A konstruktorokat többféleképpen lehet definiálni:
Az alapértelmezett konstruktor olyan konstruktor, amely nem fogad paramétereket.
Példa:
class Szemely {
public:
string nev;
// Alapértelmezett konstruktor
Szemely() {
nev = "Ismeretlen";
}
};
int main() {
Szemely s;
cout << "Név: " << s.nev << endl;
return 0;
}
Ha nem írunk saját konstruktort, a fordító automatikusan generál egy üres alapértelmezett konstruktort.
A paraméterezett konstruktor lehetővé teszi, hogy az objektum létrehozásakor értékeket adjunk át.
Példa:
class Auto {
public:
string marka;
// Paraméterezett konstruktor
Auto(string m) {
marka = m;
}
};
int main() {
Auto a1("Toyota");
Auto a2("BMW");
cout << "A1 márka: " << a1.marka << endl;
cout << "A2 márka: " << a2.marka << endl;
return 0;
}
Kimenet:
A1 márka: Toyota A2 márka: BMW
A másoló konstruktor egy másik objektum alapján hozza létre az új objektumot.
Példa:
class Ember {
public:
string nev;
// Paraméterezett konstruktor
Ember(string n) {
nev = n;
}
// Másoló konstruktor
Ember(const Ember &e) {
nev = e.nev;
}
};
int main() {
Ember e1("Gábor");
Ember e2 = e1; // Másoló konstruktor hívódik meg
cout << "E1 név: " << e1.nev << endl;
cout << "E2 név: " << e2.nev << endl;
return 0;
}
Kimenet:
E1 név: Gábor E2 név: Gábor
Ha nem írunk saját másoló konstruktort, a fordító automatikusan generál egyet.
A mozgató konstruktor lehetővé teszi a hatékony erőforrás-átadást rvalue referencia (&&
) segítségével.
Példa:
#include <iostream>
using namespace std;
class Adat {
public:
int* ptr;
// Alapértelmezett konstruktor
Adat(int ertek) {
ptr = new int(ertek);
}
// Mozgató konstruktor
Adat(Adat&& masik) {
ptr = masik.ptr;
masik.ptr = nullptr; // Az eredeti objektum erőforrását átvesszük
}
~Adat() {
delete ptr;
}
};
int main() {
Adat a1(42);
Adat a2 = move(a1); // Mozgató konstruktor fut le
return 0;
}
Ez gyorsabb, mint a másoló konstruktor, mert nem másolja az adatokat, csak áthelyezi őket.
Ha egy konstruktor csak egy paramétert fogad el, akkor implicit konverziót végezhet:
class Ember {
public:
string nev;
// Implicit konverzió lehetséges
Ember(string n) {
nev = n;
}
};
int main() {
Ember e = "Péter"; // Automatikus konverzió működik
return 0;
}
Ha ezt meg akarjuk tiltani, használhatjuk az explicit
kulcsszót:
class Ember {
public:
string nev;
explicit Ember(string n) {
nev = n;
}
};
int main() {
// Ember e = "Péter"; // Fordítási hiba!
Ember e("Péter"); // Csak ez működik
return 0;
}
Ha egy osztály egy másik osztályból öröklődik, a szülőosztály konstruktorát is meg kell hívni.
Példa:
class Szemely {
public:
string nev;
Szemely(string n) {
nev = n;
}
};
class Diak : public Szemely {
public:
int jegy;
// A szülő konstruktorának meghívása
Diak(string n, int j) : Szemely(n) {
jegy = j;
}
};
int main() {
Diak d("Ádám", 5);
cout << "Diák neve: " << d.nev << ", jegy: " << d.jegy << endl;
return 0;
}
Kimenet:
Diák neve: Ádám, jegy: 5
A Szemely(n)
hívja meg a szülőosztály konstruktorát.
C++-ban nincs virtuális konstruktor, de gyárfüggvénnyel lehet hasonlót elérni:
class Alap {
public:
virtual ~Alap() {}
virtual Alap* ujPeldany() const = 0;
};
class Szarmaztatott : public Alap {
public:
Szarmaztatott* ujPeldany() const override {
return new Szarmaztatott(*this);
}
};
A konstruktorok lehetővé teszik az objektumok helyes inicializálását, és többféle típusa van: - Alapértelmezett - Paraméterezett - Másoló - Mozgató - Explicit - Öröklött konstruktorok