La classe STD :: wstring manque certaines opérations pour les chaînes "normales" C (et littéraux).
J'aimerais ajouter ces opérations manquantes dans ma propre classe personnalisée: p> Le code ci-dessus compile une amende Ubuntu Karmic avec g ++ v4.4.1. P> mais je me demande s'il y a des arguments contre le faisant? P> Modifier : strong> Quelques exemples pour clarifier ce que je veux dire avec des "opérations manquantes": p> edit: strong> je voudrais avoir cela en quelque sorte " centralisé ". C'est parce que j'ai un projet à porter de M $ -Windows avec des milliers de ces opérations d'échec. P> La bonne chose est la suivante: il y a un endroit central où le type de chaîne à utiliser est défini, par exemple: p>
8 Réponses :
Le modèle de classe std :: basique_string code> (de lequel
std :: wstring code> est un typlef avec des arguments de modèle spécifiques) les pas em> ont un Destructeur virtuel, et en tant que tel, en héritage de celui-ci publiquement est une mauvaise idée em>. p>
C'est légal, mais beaucoup de gens le pensent indésirables. La question est que les classes de modèle de bibliothèque standard n'ont pas de destructeurs virtuels. Donc, si vous écrivez un code comme celui-ci:
std::wstring * p = new CustomWString ; ... delete p;
Vous pouvez le faire. Mais je ne vois pas de point, depuis STD :: basique_string (et ses versions en béton STD :: String et STD :: Wstring) ne définir aucune méthode virtuelle et avoir destructeurs non virtuels. Donc, il n'y a aucun moyen, vous pouvez utiliser votre sous-classe correctement à la place d'E.G. std :: wstring. p>
Eh bien, oui, ils pourraient le transmettre in-place-de wstring code>, mais l'appelant en attente d'un
wstring code> ne pouvait qu'intervoquer le comportement de base, et non rien de l'OP ajouté. Cela soulève la question de savoir pourquoi un couplage aussi puissant (EST) comme héritage est utilisé - s'il n'y a pas de justification tout aussi forte, c'est-à-dire la substituabilité de Liskov. L'héritage est généralement un moyen paresseux d'obtenir toutes les méthodes de la base sans transférer / en les enveloppant au besoin selon la composition. Mais pourquoi pas (a) faire le travail, (b) utiliser
composition code> composition, (c) utiliser des fonctions gratuites? L'héritage a tellement de pièges potentiels que les avantages doivent être importants
Je pense que vous savez que Donc, ce qui suit est dangereux: p> Utilisation directe de votre classe personnalisée est correct, par exemple p> < Pré> xxx pré> p> basic_string code> ne définit pas un destructeur virtuel. Il est faux d'utiliser
wstring code> dans un polymorphe em> de manière. Sinon, vous pouvez utiliser votre classe personnalisée comme d'habitude.
L'argument traditionnel contre hériter d'objets stl est qu'ils n'ont pas de destructeur virtuel. Alors, prenez le vecteur par exemple. Si je devais hériter de celui-ci:
int main() { std::vector<int>* vecPtr = new CMyVect(); delete vecPtr; // invokes vector constructor only, not yours }
L'absence de destructeur virtuel n'est qu'un problème lorsque vous introduisez de nouveaux membres de données. (Ce n'est pas garanti par la norme, mais une mise en œuvre du compilateur devrait se déplacer de sa façon de la casser)
@peterchen: Supposons que la classe dérivée ait un ou plusieurs membres virtuels, et la classe de base ne le fait pas. Ensuite, je suis sûr que la suppression de la classe de base ira mal, car (dans une implémentation typique), il ne pointe pas le début d'une allocation de mémoire, mais le bloc sera libéré comme si elle le faisait. Le compilateur ne sort pas de son chemin. Je pense qu'il est préférable de conseiller simplement d'éviter tout comportement non défini, plutôt que d'essayer de comprendre dans quelles conditions un compilateur «raisonnable» fera en fait quelque chose de prévisible.
(En outre, l'exemple du questionneur a un nouveau membre de données).
@peterchen La norme dit explicitement que l'absence d'un destructeur virtuel entraînera un comportement non défini si un objet dérivé est supprimé via un pointeur de base. Le fait qu'il semble fonctionner ne signifie pas que le comportement n'est pas indéfini.
@Steve: J'envisagerais d'introduire un nouveau membre de données dans ce contexte - car il modifie la représentation en mémoire. .... @Neil: Cela ne signifie pas que chaque classe a besoin d'un DTor virtuel. Je conviens que nous sommes au-delà de ce qui est sanctionné par le compilateur, cependant.
Le compilateur vous permet définitivement, car il n'ya aucun moyen de sceller une classe avec un constructeur public en C ++. P>
Les conteneurs STL ne sont pas conçus pour l'héritage strong>, donc c'est généralement une mauvaise idée. C ++ a à de nombreux angles étranges pour ignorer cela. Votre classe dérivée pourrait casser avec une autre implémentation stl, ou simplement avec une mise à jour de l'environnement de construction. p>
Cependant, je considérerais comme un panneau d'avertissement Striiong, pas un total total non. C'est un "Tu es vraiment vraiment sûr de ce que tu fais, connaissez-vous toutes les implications et avoir de bons arguments contre toutes les alternatives"? p>
Cependant, strong> Je ne suis pas sûr de savoir comment vous souhaitez implémenter chartons * c_str () code> sans fournir de stockage pour la chaîne. Et dès que vous introduisez de nouveaux membres de données, vous entrez dans un domaine de mines antipersonnel. p>
Vous avez raison concernant «Comment implémenter C_STR () sans fournir de stockage local».
Il n'y a aucun moyen de sceller une classe avec un constructeur public en C ++ code> - pour la postérité, il existe dans> = C ++ 11, qui a ajouté le mot-clé
final code> pour les deux classes et méthodes virtuelles. Je suppose qu'aucune implémentation de STDLIB n'augmente a réellement effectué des classes STDLIB
finale code>, car (a) la norme ne le stipule probablement pas et / parce que (b) il briserait toutes sortes de code (Peut-être inutilement ou même dangereusement ou même dangereusement) héritant des classes STDLIB.
C'est possible et légal. Mais c'est une mauvaise idée. Les classes ne sont pas conçues pour l'héritage et l'extension est la mieux effectuée sans héritage. Si vous ne faites pas attention lorsque en utilisant em> les classes, vous obtiendrez un comportement indéfini. (Les classes n'ont pas de destructeurs virtuels) p>
En outre, il semble une mauvaise idée d'ajouter ces fonctions spécifiques, car elles dépendent de la locale et de l'encodage. Vous donnez la classe plus qu'une responsabilité. La fonctionnalité de la conversion entre char code> et
wchar_t code> appartient ailleurs. P>
La possibilité de "hériter" d'une classe d'une autre est une caractéristique linguistique. Il s'agit simplement d'une fonctionnalité de langue formelle, plaine et sèche qui n'est pas liée à une application spécifique ou à un modèle d'utilisation spécifique. C'est un outil de bas niveau que vous pouvez utiliser à des fins différentes. Et pour répondre à votre question, il est parfaitement légal d'hériter de Cependant, la question suivante serait la question de "pourquoi". Pourquoi voulez-vous hériter de Si vous concevez votre code dans le paradigme OOP, alors héritage publiquement em> de Si vous concevez votre code dans un autre paradigme, comme par exemple, la méta-programmation de modèle (TMP), alors l'héritage public peut être une chose parfaitement valide à faire. Vous voyez, dans l'héritage public de TMP, sert un objectif complètement différent, pas même à distance lié à distance au polymorphisme et aux relations. P>
En d'autres termes, il n'ya aucun moyen de produire une réponse concrète à votre question sans prendre en compte la plus grande image. Dans tous les cas, méfiez-vous de "mécanique" réponses, comme "car std :: wstring code> classe. P>
std :: wstring code>? P>
std :: wstring code> pourrait ne pas être une bonne idée "pourrait" être un mot clé ici. L'héritage public dans OOP implique généralement une relation est une relation dans une hiérarchie de la classe polymorphe. Classe
std :: wstring code> n'est pas conçu pour être polymorphe, ce qui est la raison pour laquelle on peut en hériter publiquement de celui-ci comme une chose plutôt étrange à faire. P>
std :: wstring code> n'a pas de destructeur virtuel, vous ne pouvez pas hériter de celui-ci car il va casser
Quelles sont les opérations manquantes?
@Gman: conversions vers et depuis
char * code>, je présume.
Si c'est tout, découlant d'une classe de cordes complète semble trop tendre. Quel est le problème avec deux fonctions?
Je recommande vivement de mettre les routines de conversion en dehors de la classe. Ce n'est pas si beaucoup de travail écrit
std :: wstring str = encoder ("str"); code>. En outre, déposez que
void code> dans votre extrait, il est totalement inutile là-bas.