Orice noua definitie de clasa contine implicit 4 functii membru speciale: constructorul implicit (nu are argumente), constructorul de copie, operatorul de atribuire (supraincarcat automat la derivare!) si destructorul. Daca programatorul nu defineste explicit aceste functii membru, ele sunt generate de catre compilator.

Constructorii au rolul de a initializa datele membru ale obiectelor. Daca nu se declara un constructor pentru o clasa, iar clasa respectiva nu contine date membru const sau referinta, compilatorul declara un constructor implicit, care este functie inline, nu initializeaza datele membru si invoca constructorii claselor de baza sau continute in definitia clasei. Daca programatorul defineste macar un constructor, compilatorul nu mai genereaza automat constructorul implicit!

Crearea unui tablou de obiecte poate fi impiedicata de lipsa constructorului implicit, deoarece acesta este apelat pentru fiecare element al tabloului. (Aceeasi problema apare la utilizarea containerelor STL precum vector si list!) Tabloul poate fi, totusi, initializat cu o lista sau cu un constructor cu toti parametrii impliciti.


Exemplu:
class File{
	string path;
	int mode;
	public:
	File(const string& file_path, int open_mode);
}
...
File folder[2]={File("f1",1), File("f2", 2)};
Un constructor cu un singur argument este considerat, in mod implicit, operator de conversie; de exemplu:

class sir{
	int size;
	int capacity;
	char* buffer;
	public:
	sir();
	sir(int size);
	sir(const char*);
}
...
int main(){
	sir s = "hello"; //OK, conversia unui sir C in obiect sir, utilizand al treilea constructor
	int ns=0;
	...
	s = 1; //oops, programatorul dorea de fapt sa scrie "ns=1"!
	//compilatorul interpreteaza prin s = sir(1), apeland constructorul cu argument int
}
Blocarea acestui gen de conversie implicita se realizeaza cu explicit:

...
explicit sir(int size);
...
s = 1; //eroare la compilare!
//daca conversia este dorita, se utilizeaza s = (sir)1 sau s = sir(1)
Prevenirea instantierii unei clase se poate realiza utilizand functii virtuale pure; suprasarcina indusa de functiile virtuale face ca aceasta varianta sa fie costisitoare. Se pot folosi constructori declarati protected, astfel incat sa se poata instantia clasele derivate.

Lista de initializare a datelor membru este obligatoriu de utilizat pentru date membru const sau referinta si pentru a transmite argumente constructorilor claselor de baza. Compilatorul scaneaza lista de initializare si insereaza automat codul corespunzator in corpul constructorului. Ordinea in lista de initializare trebuie sa coincida cu ordinea in care sunt declarate datele membru ale clasei. Exemple:


1)
derived (int n, char* t): base(n, t){...}; //pasarea de argumente constructorului clasei de baza
2)
using std::string;
class WebSite{
	string URL;
	unsigned int IP;
	public:
	WebSite(){		//WebSite():URL(""), IP(0){}
		URL="";
		IP=0;
	}
}
Neutilizarea listei de initializare conduce, in acest caz, la crearea unui obiect temporar din "", atribuirea acestui obiect lui URL si distrugerea obiectului temporar; utilizarea listei de initializare evita construirea obiectului temporar!

Constructorul de copie are primul argument de tip C&, const C&, volatile C& sau const volatile C&; el nu contine argumente suplimentare sau, daca acestea exista, au toate valori implicite. Se poate bloca copierea unui obiect declarand private constructorul de copie si operatorul de atribuire.

Inainte de a intra in corpul unui constructor, obiectele sale membru trebuie sa fie initializate; de exemplu:
ordinea de apel
Ordinea de apel a constructorilor pentru un obiect de tip derived2 este:
base(), m1(), m2(), derived1(), m3(), m4(), derived2().
Ordinea de apel a constructorilor obiectelor membru (compozitie) este unica si coincide cu ordinea declararii obiectelor in clasa! Ordinea de apel a destructorilor este intotdeauna inversa celei a constructorilor.

Destructorul invoca, in ordine inversa construirii, destructorii claselor de baza sau impachetate in definitia de clasa. De exemplu:


class A{
public:
virtual ~A(){
	cout << "destructor A" << endl;
}
};
class B: public A{
public:
~B(){
	cout << "destructor B" << endl;
};
};
int main(){
B b;
}
Se afiseaza, in ordine,
	destructor B
	destructor A
Compilatorul insereaza la sfarsitul codului utilizator instructiunea:
	this->A::~A();
Un destructor poate fi (si este recomandat sa fie) virtual. Un destructor virtual pur al unei clase de baza trebuie sa aiba o definitie vida. (deoarece el este apelat automat de catre destructorul clasei derivate!)

Daca o clasa contine functii virtuale, atunci orice constructor al clasei initializeaza, inaintea executiei codului utilizator, in mod automat (dependent de implementare), pointerul catre tabela functiilor virtuale (VTABLE). Deoarece, pentru a-l initializa, constructorul trebuie sa cunoasca tipul exact al obiectului la momemtul compilarii, el NU poate fi functie virtuala! Cum s-ar putea insa simula un constructor virtual?


class browser {
public:
	browser();
	browser (const browser&);
	virtual browser* construct(){
		return new browser;       //virtual default constructor
	};
	virtual browser* clone(){
		return new browser(*this); //virtual copy constructor
	};
};
class HTMLEditor: public browser{
public:
	HTMLEditor();
	HTMLEditor(const HTMLEditor&);
	HTMLEditor* construct(){
		return new HTMLEditor;
	};
	HTMLEditor* clone(){
		return new HTMLEditor(*this);
	};
};
void create (browser& br){
	browser *pbr = br.construct();
	...
	delete pbr;
}
O functie virtuala trebuie sa se potrivesca pe semnatura si tipul returnat al functiei pe care o supraincarca! ANSI/ISO C++ a relaxat acesta cerinta, tipul returnat putand co-varia cu tipul clasei (valabil doar pentru pointeri si pentru referinte!)