void fun() {
// Allocation d'un objet de type A confié au pointeur intelligent sp
unique_ptr<A> sp(new A());
...
// Utilisation de l'objet par l'intermédiaire de sp
*sp
...
// La destruction de la variable sp libère l'objet de type A
}
// Maximum de deux entiers
int max(int m, int n) { return m > n ? m : n; }
// Maximum de trois entiers
int max(int m, int n, int p) {
return m > n ? (m > p ? m : p) : (n > p ? n : p);
}
// Maximum de deux flottants
float max(float x, float y) { return x > y ? x : y; }
// Programme principal
int main() {
cout << max(2, 3) << endl;
cout << max(2, 4, 3) << endl;
cout << max(2.3, 3.2) << endl;
}
// Classe avec toutes les méthodes fournies par défaut
class A { private: int v; };
// Utilisation du constructeur de copie pour initialiser le paramètre
A fun(A a) {
return a; // Utilisation du constructeur de copie
} // pour copier la valeur de retour
int main() {
A a; // Utilisation du constructeur par défaut
A b = a; // Utilisation du constructeur de copie
b = a; // Utilisation de l'opérateur d'affectation
b = fun(a); // Utilisations multiples
// Utilisation du destructeur par défaut pour détruire a et b
}
Depuis la version C++11, il y aussi les méthodes suivantes.
class A {
friend class F; // Classe F déclarée amie de la classe A
public:
A(int v) : val(v) {} // Constructeur
int get() { return val; } // Méthode publique de A accédant à l'attribut privé val de A
private:
int val; // Attribut privé de A
};
class F {
public:
F(int v) : val(v) {} // Constructeur
// Utilisation normale d'une méthode publique de A
int get(A a) { return val = a.get(); }
// Accès à un attribut privé de A
void set(A& a) { a.val = val; }
private:
int val;
};
int main() {
A a(-1);
F f(1);
f.set(a);
cout << a.get() << endl;
}
class A {
public: // Méthode applicable à un objet constant
void change() const { m++; }
private:
int n = 0; // Attribut non modifiable par change
mutable int m = 0; // Attribut modifiale
};
int main() {
const A a; // Object constant
a.change();
}
class B { // Classe de base
public:
// Méthode non virtuelle
void nprint() { cout << "B" << endl; }
// Méthode virtuelle
virtual void vprint() { cout << "B" << endl; }
};
class D : public B { // Classe dérivée
public:
// Redéfinition de la méthode non virtuelle
void nprint() { cout << "D" << endl; }
// Redéfinition de la méthode virtuelle
void vprint() { cout << "D" << endl; }
};
// Appel des deux méthodes nprint et vprint sur un objet
void print(B& b) { b.nprint(); b.vprint(); }
int main() {
B b; // Objet de type B
D d; // Objet de type D
print(b); // Affiche B et B
print(d); // Affiche B et D
}
class B { // Classe de base
public:
virtual ~B() = 0; // Destructeur virtuel pur
};
Le problème est qu'une telle classe B ne peut pas être utilisée.
D'une part, elle ne peut pas être instanciée car son destructeur est
virtuel. D'autre part, toute classe qui dérive directement ou non de
B ne peut pas être instanciée non plus car son destructeur doit
appeler le destructeur de sa classe de base qui n'existe pas. Pour que
B ou une classe dérivée de B puissent être instanciée,
il est possible d'ajouter une définition par défaut du destructeur tout
en le laissant virtuel pur.
B::~B() { ... }
Dans ce cas, le fait d'être virtuel pur pour le destructeur n'a plus
d'intérêt car un destructeur n'est pas hérité par une classe dérivée.