Ok, c'est vraiment difficile à avouer, mais j'ai une forte tentation en ce moment d'hériter de std::vector
.
J'ai besoin d'environ 10 algorithmes personnalisés pour le vecteur et je veux qu'ils soient directement membres du vecteur. Mais naturellement, je veux aussi que le reste des algorithmes du vecteur soient des membres du vecteur. std::vector
de l'interface. Eh bien, ma première idée, en tant que citoyen respectueux de la loi, était d'avoir une std::vector
membre en MyVector
classe. Mais alors je devrais manuellement reprovider toute l'interface de std::vector. Trop de choses à taper. Ensuite, j'ai pensé à l'héritage privé, de sorte qu'au lieu de fournir à nouveau des méthodes, j'écrirais un groupe de using std::vector::member
dans la section publique. C'est également fastidieux en fait.
Et voilà, je pense vraiment que je peux simplement hériter publiquement de std::vector
mais prévoyez un avertissement dans la documentation indiquant que cette classe ne doit pas être utilisée de manière polymorphe. Je pense que la plupart des développeurs sont suffisamment compétents pour comprendre que cette classe ne doit pas être utilisée de manière polymorphe de toute façon.
Ma décision est-elle absolument injustifiable ? Si oui, pourquoi ? Pouvez-vous proposer une alternative qui aurait les membres supplémentaires suivants en fait mais qui n'impliquerait pas de retaper toute l'interface du vecteur ? J'en doute, mais si vous le pouvez, je serai heureux.
En outre, outre le fait qu'un idiot peut écrire quelque chose comme
std::vector<int>* p = new MyVector
Y a-t-il un autre réaliste péril dans l'utilisation de MyVector ? En disant réaliste, j'écarte des choses comme imaginer une fonction qui prend un pointeur sur le vecteur ...
Eh bien, j'ai exposé mon cas. J'ai péché. Maintenant c'est à vous de me pardonner ou pas :)
2 votes
Re :
std::vector<int>* p = new MyVector
ne fonctionne pas vraiment en premier lieu, car std::vector n'a pas de destructeur virtuel. Il y aura très certainement un comportement non défini dans un futur proche.9 votes
Donc, en gros, vous demandez si vous pouvez violer une règle commune parce que vous êtes trop paresseux pour réimplémenter l'interface du conteneur ? Alors non, ce n'est pas le cas. Vous voyez, vous pouvez avoir le meilleur des deux mondes si vous avalez cette pilule amère et faites les choses correctement. Ne soyez pas ce type de personne. Écrivez du code robuste.
0 votes
Pourquoi le passage d'un pointeur à un vecteur dans une fonction paramétrique est-il irréaliste ?
8 votes
Pourquoi ne pouvez-vous pas/ne voulez pas ajouter la fonctionnalité dont vous avez besoin avec des fonctions non-membres ? Pour moi, ce serait la chose la plus sûre à faire dans ce scénario.
0 votes
@Crashworks : Probablement que puisque personne n'alloue les vecteurs dynamiquement, aucune fonction qui reçoit un pointeur vers un vecteur n'essaiera de le supprimer ? En dehors de cela, le type statique de l'argument sera un vecteur, et cela devrait être juste parfait.
13 votes
@Jim :
std::vector
L'interface de C+ est assez vaste, et lorsque C++1x arrivera, elle s'étendra considérablement. Il y a beaucoup de choses à taper et encore plus à étendre dans quelques années. Je pense que c'est une bonne raison d'envisager l'héritage plutôt que le confinement - si l'on suit le principe que ces fonctions devraient être des membres (ce dont je doute). La règle pour ne pas dériver des conteneurs STL est qu'ils ne sont pas polymorphes. Si vous ne les utilisez pas de cette façon, elle ne s'applique pas.9 votes
La vraie question est dans cette phrase : "Je veux qu'ils soient directement membres du vecteur". Rien d'autre dans la question ne compte vraiment. Pourquoi "voulez-vous" cela ? Quel est le problème de fournir cette fonctionnalité en tant que non-membres ?
3 votes
Comme je l'ai mentionné dans un commentaire à la réponse de Karl, la mise en cache est difficile à mettre en œuvre dans les non-membres.
3 votes
Désolé pour mon ignorance, mais beaucoup de classes que j'écris n'ont pas de destructeurs virtuels, j'en hérite, mais je ne les utilise pas de manière polymorphe. Qu'y a-t-il de spécial avec les conteneurs std et le fait d'en hériter ?
2 votes
@rafak : Les conteneurs standards n'ont rien de spécial à cet égard. Mais il est suspect d'hériter publiquement de cualquier si vous n'avez pas l'intention de l'utiliser de manière polymorphe : si vous ajoutez simplement des méthodes de commodité, il est préférable de les écrire en tant que fonctions libres, car elles peuvent alors être utilisées avec des objets existants du type de base.
D
contiennent unB
plutôt que d'en hériter, afin d'éviter le risque de "polymorphisme accidentel" (avoir unD
traité comme unB
et de briser ces invariants), même si cela représente plus de travail.7 votes
Je vais être franc. En disant : " fournir un avertissement dans la documentation indiquant que cette classe ne doit pas être utilisée de manière polymorphe. Je pense que la plupart des développeurs sont suffisamment compétents pour comprendre que cette classe ne doit pas être utilisée de manière polymorphe de toute façon. "est vraiment un vœu pieux. Vous créerez un terrain fertile pour de futurs problèmes en lésinant sur quelques lignes de code aujourd'hui. En un clin d'œil, les "autres développeurs" ignoreront la documentation et feront des choses qu'ils ne sont "pas censés" faire. N'oublie pas que tu fais aussi quelque chose que tu n'es "pas censé" faire. . ;)
0 votes
Tu ne dois pas mal écrire "shall" comme "shalt".
8 votes
@JoshC : "Thou shalt" a toujours été plus courant que "thou shall", et c'est également la version que l'on trouve dans la Bible du roi Jacques (qui est généralement ce à quoi les gens font allusion lorsqu'ils écrivent "thou shalt not [...]"). Qu'est-ce qui peut bien vous amener à parler de "faute d'orthographe" ?
0 votes
Certains de ces arguments sont basés sur le fait que d'autres développeurs se sont plantés parce qu'ils n'ont pas compris correctement vos implémentations std::container-inherrited... mais si vous êtes le seul développeur et que vous vous attendez toujours à l'être, vous pouvez au moins écarter ces arguments, n'est-ce pas ?