- override + const (chipotage)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | class A {
public:
virtual int f() const = 0;
};
class B : public A {
public:
int f() const override {
return 0;
}
};
class C : public A {
public:
int f() const override {
return 1;
}
};
|
On déclare un vecteur de shared_ptr vers des classes héritant de A. Comme dit précédemment, on ne peut pas utiliser directement les objets, parce qu'ils sont susceptibles d'avoir des tailles différentes, ce qui pose de sérieux soucis. On n'utilise pas non plus de unique_ptr parce que ces derniers ne permettent pas d'appeler les bons destructeurs (cf. StackOverflow : Virtual destructor with virtual members in C++11).
Je rejoins Praetonus sur ce point : définir une classe et comment elle devra être utiliser est très casse gueule.
La regle des 5/0 ne s'appliquent que lorsque l'on définit (explicite define) un comportement particulier dans l'une des fonctions concernées. Utiliser default (= implicite defined, explicite declared) ne nécessite pas de redéfinir les autres fonctions, donc on respecte la règle du 0.
De même pour la move et la copy, l'implicite defined ne bloque pas leur génération automatique.
En termes de coût, shared_ptr va devoir conserver un deleter dans le control bloc (~ 1 pointeur), un destructeur virtuel idem (pour la vtable). Donc coût identique sur ce point.
Par contre shared_ptr va ajouter également d'autres données dans le control bloc, en particulier 2 compteurs atomiques (ou 1 ? Bonne question, je ne sais pas si le compteur pour les weak est atomique ou non). Bref, surcoût important.
Et j'ajouterais que cela donne une sémantique ("cet objet possède plusieurs propriétaires") qui n'est pas vrai (il n'y a pas d'ownership partagé).
Donc très mauvaise pratique à mon sens.
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 <memory>
#include <vector>
class A {
public:
virtual ~A() = default;
virtual int f() const = 0;
};
class B : public A {
public:
int f() const override {
return 0;
}
};
class C : public A {
public:
int f() const override {
return 1;
}
};
int main() {
std::vector<std::unique_ptr<A>> vec { //j'ai un doute sur cette syntaxe
std::make_unique<B>(),
std::make_unique<C>(),
std::make_unique<B>(),
std::make_unique<C>()
};
for(auto& elem: vec) {
std::cout << elem->f() << std::endl;
}
return 0;
}
|