Bonjour,

je viens vous parler de quelque chose qui m'a toujours posé problème: l'utilisation de pointeurs intelligents dans un conteneur de la STL.

Prenons l'exemple suivant:
Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>
#include <vector>
#include <memory>
 
class Shape {
public:
	virtual void display() = 0;
};
 
class Triangle : public Shape {
public:
	void display() override	{
		std::cout << "Triangle::display()" << std::endl;
	}
};
 
class Renderer {
public:
	void createTriangle() {
		shapes_.emplace_back(std::make_unique<Shape>(new Triangle));
	}
 
	void display() {
		for (auto& shape : shapes_)
			shape->display();
	}
 
private:
	std::vector<std::unique_ptr<Shape>> shapes_;
};
 
int main()
{
	Renderer renderer;
	renderer.display();
 
	return 0;
}
J'ai un Renderer qui va posséder une liste de Shape. Ici, je n'ai que Triangle, mais l'idée est évidemment d'en implémenter d'autres (carré, ...).

Le code ci-dessus ne compile pas, et pose deux problèmes:
1) Le premier se pose au niveau de l'instanciation d'une Shape:
Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
shapes_.emplace_back(std::make_unique<Shape>(new Triangle));
Ici j'ai une erreur de compilation parce que Shape est une classe abstraite et qu'elle n'est donc pas instanciable. Mais je ne comprends pas: je ne veux pas l'instancier, je veux juste créer un pointeur. Pourquoi ça fonctionne si je fais exactement la même chose avec des pointeurs nu, mais pas avec des pointeurs intelligents? Notez que j'ai essayé de remplacer, dans ce code, les unique_ptr par des shared_ptr, et le résultat est le même.

2) Mon deuxième problème se situe au niveau de la boucle qui appelle une fonction membre de l'objet contenu:
Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
for (auto& shape : shapes_)
	shape->display();
J'ai écrit ce code à titre indicatif, mais je crois qu'il ne compile pas. Comment pourrait-il compiler puisque j'essaie d'utiliser shape comme un pointeur (en utilisant l'opérateur ->), alors que c'est une référence?
Mais je ne parviens pas à trouver une façon simple et élégante d'implémenter cette boucle. Puisque mon vecteur contient des unique_ptr, ces derniers ne peuvent pas être copiés. Donc je ne peux pas faire for( auto shape : shapes_). Mais alors comment faire?

Conclusion: il y a beaucoup de choses que je ne comprend pas dans cette histoire. Et tout ça me parait fort compliqué pour quelque chose de simple. Car faire la même chose avec des pointeurs nu est la chose la plus simple du monde, alors pourquoi ça devient si compliqué lorsqu'on veut utiliser des pointeurs intelligents?
Globalement, je pense que je m'y prend mal. Mais ou est mon erreur? Peut-être ne devrais-je pas utiliser le polymorphisme?