Limbajul C cu clase a oferit suport pentru incapsulare si ascunderea informatiei. O clasa ofera separarea implementarii interne (supusa schimarilor) de interfata externa.

In 1983 C-ul cu clase a suferit modificari si extensii, adoptandu-se numele de C++. (Sufixul ++ a devenit, inca de pe atunci, simbolul orientarii spre obiecte).

Intre 1985 si 1989 C++ a suferit o reforma majora: au fost adaugate membri si mostenire de tip protected, template-uri si mostenire multipla. Din acel moment a devenit clara necesitatea standardizarii.

In 1989 s-a reunit comitetul ANSI (American National Standards Institution) pentru standardizarea C++ sub numele X3J16 (ulterior, modificat in J16). In mai multi pasi (1996, 1997 si 1998) s-a reusit adoptarea unui standard care sa capete o recunoastere internationala(ISO - International Standardization Organization).

Limbajul C++ de astazi este foarte diferit de cel numit initial asa in 1983. Aceasta face necesara precizarea terminologiei:
O unitate de traducere (in cod obiect) contine o secventa de declaratii. Se prefera utilizarea acestui termen deoarece o unitate de traducere poate fi asamblata din mai multe fisiere sursa. Un program consta astfel din mai multe unitati de traducere link-editate impreuna.

O l-valoare este o expresie care se refera la un obiect (zona continua de memorie). Definitia initiala considera l-valoarea drept o entitate care apare in stanga unei atribuiri; totusi, un obiect const este o l-valoare care nu poate fi utilizata in stanga unei atribuiri. O l-valoare poate aparea intr-un context in care este necesara prezenta unei r-valori; in acest caz se efectueaza o conversie implicita.

O r-valoare este o expresie care poate aparea doar in dreapta unei atribuiri. O r-valoare nu poate fi convertita intr-o l-valoare!

#include <string>
using namespace std;
int& f();
void func(){
  int n;
  char buf[3];
  n=5; 			//n este l-valoare, 5 este r-valoare
  buf[0]='a'; 		//buf[0] este l-valoare, 'a' este r-valoare
  string s1="a", s2="b", s3="c"; //"a","b","c" sunt r-valori
  s1=       		//l-valoare
     s2+s3; 		//l-valori convertite implicit in r-valori
  s1=           	//l-valoare
     string("z"); 	//r-valoare temporara
  int* p= new int; 	//p este l-valoare, 'new int' este r-valoare
  f()=0; 		//un apel de functie care returneaza o referinta este o l-valoare
  s1.size(0); 		//altfel, un apel de functie este o r-valoare
}

ODR: Intr-un program orice entitate trebuie definita o singura data!
O clasa, o enumerare, o functie inline cu linkage extern, o clasa sablon, o functie sablon ne-statica, o functie sablon membru, o data membru statica a unei clase sablon si o specializare a unui sablon pentru care nu se precizeaza anumiti parametri pot fi definite de mai multe ori intr-un program: fiecare definitie trebuie sa apara in unitati de traducere diferite si trebuie sa contina acceasi secventa de atomi (atomii sa fie semantic echivalenti).

//exemplul 1
//fisierul first.cpp
inline int C::getVal() {return 5;}
//fisierul sec.cpp
typedef int I;
inline I C::getVal(return 5;) //incalcare ODR: I si int nu sunt atomi identici!

//exemplul 2
//fisierul first.cpp
typedef int I;
inline I C::getVal(){return 5;}
//fisierul sec.cpp
typedef unsigned int I;
inline I C::getVal(){return 5;} //incalcare ODR: contexte semantice diferite pentru I!

Un nume care poate fi referit din alte unitati de traducere sau din alte scopuri ale aceleiasi unitati de traducere are linkage extern. Exemple:

void g(int n){}			//o functie are linkage extern
int glob;       		//o variabila globala are linkage extern
extern const int E_MAX=1024;	//E_MAX are linkage extern
namespace N{
int num;     			//N::num are linkage extern
void func(); 			//N::func are linkage extern
}
class C{};   			//un nume de clasa are linkage extern

Un nume care poate fi referit din alte scopuri ale aceleiasi unitati de traducere, dar nu si din alte unitati de traducere, are linkage intern. Daca un nume nu poate fi referit in afara scopului in care a fost declarat, el nu are linkage! De exemplu:

static void func(){} 	//func are linkage intern
union{               	//membrii unei uniuni anonime ne-locale au linkage intern
  int n;
  void *p;
};
const int MAX=1024; 	//constantele au implicit linkage intern
typedef int I;      	//numele I are linkage intern
void f(){
  int a;     		//a nu are linkage
  class B{}; 		//un nume de clasa locala nu are linkage
} 

Un efect colateral este o modificare a mediului de executie. Modificarea unui obiect, accesarea unui obiect de tip volatile, invocarea unei functii din libraria I/O sau apelarea unei functii care efectueaza una dintre aceste operatii sunt toate efecte colaterale.

Comportamentul dependent de implementare este acela pe care trebuie sa-l documenteze orice implemetare de compilator C++, cum ar fi dimensiunea tipurilor fundamentale. Se refera la mecanismele ascunse ale implementarii, in general neaccesibile utilizatorilor.

Comportamentul nespecificat depinde de implemetare; nu este cerut, dar este permis ca implementarea sa documenteze acel comportament. Se refera constructiile de limbaj pe care utilizatorii le pot accesa direct. De exemplu, este nespecificat daca operatorul new apeleaza sau nu functia C standard malloc.

Comportamentul nedefinit este acela asupra caruia standardul nu impune nici o cerinta. De exemplu, efectul accesarii elementelor unui tablou in afara limitelor acestuia este nedefinit.