11
votes

Extension de classe C ++

Y a-t-il un moyen d'ajouter de nouvelles méthodes à une classe, sans modifier la définition de la classe d'origine (c'est-à-dire la classe compilée de classe et le fichier de classe correspondant) comme des méthodes d'extension de classe C #?


1 commentaires

Pour une référence future, cela s'appelle «patching singe».


9 Réponses :


19
votes

Non. C ++ n'a aucune capacité de ce type.

Comme mentionné dans d'autres réponses, les solutions de contournement commun sont:

  • Définissez une classe dérivée, peut-être avec une usine pour masquer la classe de mise en œuvre réelle
  • Définissez un décorateur classe
  • Définir les fonctions non membres qui fonctionnent sur des instances de la classe

1 commentaires

Peut aussi être fait par Double Dispatch



12
votes

Non, vous ne pouvez pas faire cela en C ++.

Si vous voulez réaliser quelque chose comme celui-ci, vous avez 2 options,

  • Vous pouvez hériter de la classe (s'il s'agit d'une option, il pourrait ne pas être légal car la classe n'aurait peut-être pas été écrite pour autoriser l'héritage)
  • Vous pouvez écrire votre propre classe wrapper qui possède la même interface + vos nouvelles méthodes et déléguées à celui que vous souhaitez prolonger.

    Je préfère l'approche de la délégation.


2 commentaires

Bonne réponse - mais je ne suis pas sûr que quelqu'un posant des questions comme celles-ci sait de savoir quoi mettre en œuvre lorsqu'il entend des termes tels que "hériter" ou "délégué".


@mh, probablement pas. Mais maintenant, ils connaissent les termes corrects à mettre dans une recherche à une ou Google



-3
votes

désolé, non. Une fois que votre code est à Obj, vous ne pouvez pas le changer. Si cela peut être fait dans les classes partielles VC serait déjà pris en charge. Il existe une exception par exception, les méthodes de l'opérateur peuvent être étendues à l'aide de fonctions globales, jolie comme la manière dont Cout << est implémentée dans STL.


0 commentaires

5
votes

C # Classe Les méthodes d'extension sont principalement du sucre syntaxique. Vous obtenez la même fonctionnalité avec des fonctions libres (c'est-à-dire des fonctions avec une référence ou une référence constante à votre classe comme premier paramètre). Puisque cela fonctionne bien pour la STL, pourquoi pas pour votre classe?


0 commentaires

-3
votes

Bien sûr, vous pouvez:

template <typename Ext>
class Class: public Ext { /* ... */ };


0 commentaires

1
votes

Généralement pas. Toutefois, si la bibliothèque ne crée pas d'autres instances de la classe nécessitant votre extension et que vous êtes en mesure de modifier tous les endroits de l'application qui créent une instance de la classe et nécessitent vos extensions, il existe une façon de choisir:

  • Créez une fonction d'usine appelée à tous les endroits nécessitant une instance de la classe et renvoie un pointeur sur l'instance (Google pour des motifs de conception usine , ...).
  • Créez une classe dérivée avec les extensions que vous voulez.
  • Faites de la fonction d'usine renvoyer votre classe dérivée au lieu de la classe d'origine.

    Exemple: xxx

    • Chaque fois que vous avez besoin d'accéder aux extensions, vous devez voter dans la classe dérivée, bien sûr.

      C'est à peu près comment mettre en œuvre la méthode "hériter" suggérée par GLEN. La méthode "Wrapper Class avec la même interface" de Glen est également très belle d'un point de vue théorique, mais a des propriétés légèrement différentes qui le rend moins probable de travailler dans votre cas.


0 commentaires

0
votes

Il y a une solution dans laquelle cela peut être fait. Et c'est en relaxant vos besoins un peu. En C ++, les gens disent souvent que l'interface d'une classe consiste à non seulement de ses fonctions membres, mais de toutes les fonctions qui fonctionnent sur la classe .

C'est-à-dire que des fonctions non membres pouvant être attribuées à la classe sous forme de paramètre doivent être considérées comme faisant partie de son interface.

Par exemple, std :: Recherche (Rechercher () ou std :: Trier () Fait partie de l'interface de std :: vecteur , même s'ils ne sont pas membres de la classe.

Et si vous acceptez cette définition, vous pouvez toujours prolonger une classe simplement en ajoutant des fonctions non membres.


0 commentaires

0
votes

Vous ne pouvez pas ajouter de méthodes ou de données physiquement au fichier de classe qui est sous forme binaire. Cependant, vous pouvez ajouter des méthodes et des données (fonctionnalité et état) aux objets de cette classe en écrivant des classes d'extension. Ce n'est pas simple et nécessite une programmation basée sur des protocoles méta-objets-protocoles et des interfaces. Vous devez faire beaucoup pour y parvenir à C ++, car il ne supporte pas la réflexion hors de la boîte. Dans une telle mise en œuvre lorsque vous interrogez pour l'interface implémentées par votre nouvelle classe d'extension via le pointeur d'objet de classe d'origine, la mise en œuvre de l'objet META renvoie ce pointeur d'interface via l'objet META Class pour la classe d'extension qu'elle crée au moment de l'exécution. C'est combien de cadres d'application logicielle personnalisables (plugin) fonctionnent. Toutefois, vous devez vous rappeler que de nombreux autres mécanismes de MOP doivent être écrits pour instancier des objets méta pour toutes les classes à l'aide de dictionnaires dans lesquels les relations d'objet sont décrites et donnent les pointeurs d'interface appropriés pour les objets de classe d'origine et étendus. Dassault Systemes 'Catia V5 est écrit dans une telle architecture appelée CAA V5 où vous pouvez étendre les composants existants en écrivant de nouvelles classes d'extension avec la fonctionnalité souhaitée.


0 commentaires

4
votes

en C ++ Vous pouvez utiliser des fonctions libres, mais parfois des méthodes d'extension fonctionnent mieux lorsque vous nichez de nombreuses fonctions ensemble. Jetez un coup d'œil à ce code C #: xxx pré>

Si nous devons écrire cela en C ++ à l'aide de la fonction libre, il ressemblerait à ceci: p>

if (numbers | contains(5)) printf("We have a 5");


1 commentaires

omg, c'est tellement cool