2010-10-05 6 views
2

Je dois élaborer un petit cadre qui va être utilisé par plusieurs de nos applications. En plus de cela, le framework va être utilisé plusieurs fois dans la même application, mais avec une configuration légèrement différente. La 'nature' de la configuration est plus complexe que de simplement avoir des options de configuration et des setters. En pratique, l'application doit fournir ses propres structures de données qui seront intégrées dans le cadre, ce qui le rendra encore plus complexe.Classes de base versus gabarits versus code généré versus macro

Je peux voir les 4 alternatives suivantes par écrit le cadre:

  • Mettez la logique commune dans une classe de base, et indiquer à l'application qu'il doit hériter de cette classe de base
  • Mettez la logique une classe basé sur un modèle, dans lequel l'application doit passer sa propre implémentation de classe
  • Décrire la configuration spécifique de l'application dans un fichier de configuration et générer du code C++ au cours du processus de construction
  • Fournir de macro qui peuvent être utilisés pour développer t il 'configuration' au code réel

Quels arguments doivent être pris en compte lors du choix d'une bonne alternative?

Certaines de ces alternatives sont-elles meilleures que d'autres, et pourquoi?

Notez que dans mon cas, la performance est une priorité absolue.

+0

"La performance est une priorité absolue" C'est ce que tout le monde dit. –

+0

@John, dans mon cas (applications de simulation mathématique avec des millions de structures de données, prenant jusqu'à 8 Go de mémoire) la performance est en effet la priorité absolue. Un appel virtuel inutile ou un accès indirect au pointeur peut être la différence entre une application utilisable ou une application inutilisable. – Patrick

Répondre

1

J'évite l'exécution polymophism si des performances de pointe est vraiment un problème, non seulement parce que la recherche vtable pour les appels de fonctions virtuelles, mais parce que:

  • inline appels virtuels pour permettre l'optimisation des limites de la fonction cross efficace est un peu difficile à do (la même chose s'applique au code généré compilé dans une bibliothèque partagée chargée à l'exécution ("plugin") et aux modules liés statiquement compilés à partir du code généré en utilisant un compilateur qui ne supporte pas les optimisations de temps de liaison).
  • objets polymorphes doivent généralement être tas alloué pour éviter le découpage, peut-être créer en tête d'exécution supplémentaire

macros ont tendance à être difficiles à déboguer, donc à moins que vous avez besoin de leur capacité à faire concaténations de chaînes, ce qui est leur avantage distinctif Sur les modèles dans certains cas, je choisirais personnellement une solution basée sur un modèle utilisant des techniques de polymorphisme statique comme, comme vous l'avez indiqué, les curiously recurring template pattern et/ou, le cas échéant, les spécialisations de modèles pour gérer les structures de données personnalisées.

0

Utilisez un fichier d'en-tête spécifique à la plate-forme. C'est une alternative supplémentaire, similaire aux macros mais sans le croupion.

Si vous devez utiliser des macros, faites-le uniquement dans l'en-tête de configuration qui inclut l'en-tête spécifique à la plate-forme. Mais généralement, il suffit de définir des structures spécifiques à la plate-forme et de les utiliser comme sous-objets.

0

Qu'entendez-vous par performance? Si c'est la performance du code final en cours d'exécution, rappelez-vous que la solution avec l'héritage de classe qui implique la fonction virtuelle impliquera une petite surcharge lors de leur appel. D'autres solutions induisent un surcoût supplémentaire pour la phase de construction du projet et également un exécutable légèrement plus important en raison de la «duplication» du code (via la concrétisation de gabarit, la génération de code personnalisé ou la macro expansion).