web-dev-qa-db-fra.com

Pourquoi std :: future et std :: promise ne sont-ils pas définitifs?

Je blesse pourquoi les cours std::future et std::promise ne sont pas marqués avec le spécificateur final. Le destructeur n'est pas virtuel, alors pourquoi final n'a-t-il pas été ajouté? Quelle était (est) la justification?

14
Sonic78

Selon [dérivation]/4 :

Tous les types spécifiés dans la bibliothèque standard C++ doivent être des types non finaux sauf indication contraire.

Et std::future ou std::promise ne sont pas exclus.

Et comme mentionné dans un commentaire, cette question a déjà été discutée. Les développeurs de bibliothèque ont-ils la liberté d'ajouter des composants finaux aux composants non polymorphes? .

La résolution de ce problème était qu'il n'était pas considéré comme un défaut avec la conclusion:

À moins que la bibliothèque n'utilise le mot clé final dans une spécification, l'utilisateur a clairement la liberté de dériver d'une telle classe, et donc tout aussi clairement, le vendeur de la bibliothèque n'a pas la liberté de ajouter un final surcharge ou attribut de classe.

16
P.W

Jetez un oeil à cet exemple artificiel (certes absurde) avec std::vector:

template <class T>
struct Example : private std::vector<T> {
   void doStuff(const T& t) { this->Push_back(t); }
   T retrieveStuff() { return this->operator[](0); }
};

Example<int> e;

e.doStuff(42);
std::cout << e.retrieveStuff() << "\n";

Cela fonctionne, vous ne pouvez pas entrer dans UB en raison de std::vector::~vector n'étant pas virtual car vous ne pouvez pas supprimer un objet via un pointeur de classe de base (l'héritage public est nécessaire à cet endroit).

L'héritage ici n'est qu'un détail d'implémentation. Pas de pratique recommandée, mais les gens l'ont probablement fait et le font. Une fois la décision prise de ne pas casser le code existant en faisant std::vector ou d'autres types de conteneurs final, il est logique de s'en tenir à cela avec différents types de vocabulaire comme std::promise ou std::future.

19
lubgr

L'absence de toute fonction virtuelle dans une classe ne la rend pas non qualifiable comme classe de base. À mon avis, l'ajout de fonction (s) virtual à la classe de base est une sorte de spécial cas de rendre la classe de base polymorphe. Beaucoup de programmeurs imprudents mettent virtual aux fonctions, et surtout au destructeur de la classe (et commentent que "Le destructeur virtuel est nécessaire" ) .

ATL, par exemple, s'appuie fortement sur l'héritage mais n'a pas de fonctions virtuelles. Les classes (de base) sont non polymorphes. La plupart (sinon la totalité) des classes C++/STL sont non polymorphes.

On peut enfreindre la règle de "Préférer le confinement/la composition à l'héritage" et dériver d'une classe sous une forme illogique (Un exemple donné par lubgr); mais cela est faisable et valide. Parfois, il est plus approprié d'hériter d'une classe non polymorphe plutôt que de contenir une classe.

Les classes Template/Template-meta reposent sur l'héritage où aucune fonction virtuelle n'est impliquée. L'héritage des attributs en est un exemple, où une classe hériterait de différentes classes différentes (héritage multiple) et hériterait des attributs.

Un exemple très simple serait de faire une classe non_copyable, placez le constructeur de copie/opérateur d'affectation, etc. comme privé/protégé; et laisser d'autres classes en hériter. De cette façon, la classe "dérivée" hériterait de la "capacité/attribut" non copiable de la classe de base.

0
Ajay