Appel de méthodes de classe overriden en tant que chaîne en C ++

à plusieurs resockets, j’ai ressenti le besoin de définir des méthodes de classe appelées de manière similaire aux constructeurs ou aux destructeurs.

Un exemple spécifique serait; dans un programme, j’avais un réseau très complexe de nœuds de types différents qui dépendaient les uns des autres de manière très irrégulière (le réseau ne ressemblait pas du tout à un arbre). Lorsqu’un nœud devait être détruit, il entamait une chaîne complexe de destructions dans le réseau. Un peu comme une canvas d’araignée déchirée, mais plus complexe.

Lors de l’exécution de cette chaîne, le contrôle revenait aux méthodes de l’initiateur (ou de l’un des éléments intermédiaires de la chaîne), de sorte que la destruction effective devait avoir lieu lorsque la chaîne s’était installée, et c’est pourquoi je n’ai pas pu. t utilisez des destructeurs à cette fin. Cependant, le long de la hiérarchie de classes de mes nœuds, il me fallait un “destructeur du type”, c’est-à-dire un moyen d’appel à une échelle pour appeler ma fonction de pré-destruction non destrucsortingce (pour exactement les mêmes raisons pour lesquelles un destructeur réel est également appelé ainsi: chaque étape de la hiérarchie de classe devait consortingbuer à la chaîne d’une manière différente).

J’ai fini par coder l’échelle à la main. Notamment, la classe nodeBase a une méthode appelée “preDestroyNodeBase” qui fait son travail et appelle la méthode virtuelle “preDestroyNode” et ainsi de suite jusqu’à la feuille (je sais, de cette façon, cela ressemble à un constructeur, mais elle était – de manière comparée – plus élégante De cette façon, vous pouvez simplement appeler le “preDestroy” de la classe la plus basique).

Vous pouvez imaginer à quel point cette approche est sujette aux erreurs, sans parler de laide. Existe-t-il une méthode plus propre d’émuler des méthodes d’appel de type constructeur ou destructeur? Une sorte de modèle de magie ou même de macro! Parce que le codage manuel est trop sujet aux erreurs, même pour un seul programmeur, je ne peux donc pas imaginer exposer ce type de comportement aux clients d’une bibliothèque.

Peut-être me manque-t-il un concept de programmation fondamental qui rend obsolète le besoin de telles fonctions. Si tel est le cas, je serais heureux si vous indiquiez comment cet exemple de réseau de nœuds pourrait être traité.

Merci beaucoup!

Lorsque vous déclarez une fonction virtuelle, il appelle le gestionnaire le plus dérivé de la fonction. Ensuite, chaque gestionnaire appelle le gestionnaire NextMostDerivedClass::preDestroy et les appels sont NextMostDerivedClass::preDestroy vers le gestionnaire le plus dérivé de la fonction, et vous pouvez à nouveau appeler NextMostDerivedClass::preDestroy , etc. Ce chemin est identique au chemin emprunté par un destructeur virtuel, sauf que vous n’avez rien à appeler manuellement avec des destructeurs, c’est automatisé. Si vous deviez placer les instructions cout de l’exemple de code ci-dessous dans vos destructeurs, vous pourriez obtenir le même résultat que celui fourni par l’exemple ci-dessous.

 #include  class Foo { public: virtual void PreDestroy() { cout << "Foo preDestroy"; } } class Bar : public Foo { public: void PreDestroy() { cout << "Bar preDestroy\n\n"; Foo::PreDestroy(); } } class MostDerived : public Bar { public: void PreDestroy() { cout << "MostDerived preDestroy\n\n"; Bar::PreDestroy(); } } int main() { MostDerived testObj; testObj.PreDestroy(); } 

La sortie devrait être:

La plupart des pré-détruits

Bar preDestroy

Foo preDestroy

Vous pouvez utiliser le modèle de visiteur pour parcourir votre graphique de noeuds (je suppose que vous parlez de graphique) et laisser les noeuds se mettre eux-mêmes dans une sorte de liste “à supprimer” (si nécessaire) qui est conservée par l’object visiteur. Dans une seconde itération, vous pouvez parcourir cette liste d’éléments et appeler une sorte de méthode “détruire”, ce qui effectue le nettoyage final. Cette approche nécessite que tous vos nœuds prennent en charge le modèle de visiteur et contiennent cette méthode “destroy”.

J’utiliserais un mécanisme d’abonnement dans lequel, si vous voulez que le pointeur soit maintenu par un pointeur sur un autre object, vous devez également vous abonner à son événement de destruction. lors de la réception d’un tel événement, annulez leur inscription à votre propre événement et nettoyez vos propres structures (ce qui pourrait entraîner d’autres destructions).

ie (syntaxe C ++ 1x pour la brièveté)

 struct node { ~node() { for(auto i : subscribers) i->notify(this); } void subscribe(node *n) { subscribers.push_back(n); } void notify(node *n) { subscribers.remove(n); /* Handle other node being removed */ } private: std::list subscribers; } 

Pour avoir access aux membres de données du nœud, vous devez en faire des sous-objects de la classe de nœuds, soit en étendant la classe de nœud elle-même, soit en utilisant une classe de nœud basée sur un modèle qui hérite de la classe contenant les données.