Question

Je travaille sur un projet assez complexe, une routine de chiffrement personnalisée si vous voulez (juste pour le plaisir) et j'ai rencontré ce problème lors de la conception de la disposition de mon code.

J'ai un certain nombre de fonctions que je veux pouvoir appeler par index. Plus précisément, je dois pouvoir en appeler un de manière aléatoire pour le processus de chiffrement, puis l’adresser par un index spécifique dans le processus de déchiffrement.

Je pensais à un tableau de fonctions classique, mais ma principale préoccupation est qu’un tableau de fonctions serait difficile à maintenir et un peu moche. (L'objectif est de placer chaque paire de fonctions dans un fichier séparé, afin de réduire les temps de compilation et de rendre le code plus facile à gérer.) Quelqu'un a-t-il une solution C ++ plus élégante comme alternative au tableau de fonctions? La vitesse n'est pas vraiment un problème, je suis plus inquiet pour la maintenabilité.

-Nicholas

Était-ce utile?

La solution

Vous pourriez écrire quelque chose comme:

class EncryptionFunction
{
public:
    virtual Foo Run(Bar input) = 0;
    virtual ~MyFunction() {}
};

class SomeSpecificEncryptionFunction : public EncryptionFunction
{
    // override the Run function
};

// ...

std::vector<EncryptionFunction*> functions;

// ...

functions[2]->Run(data);

Vous pouvez utiliser operator () au lieu de Exécuter comme nom de fonction, si vous préférez.

Autres conseils

Qu'est-ce qui ne va pas avec le tableau de fonctions?

Vous devez appeler des fonctions par index. Ils doivent donc être placés dans des "indexables par index". structure en quelque sorte . Array est probablement la structure la plus simple qui répond à ce besoin.

Exemple (si je ne sais pas comment compiler):

struct FunctionPair {
   EncodeFunction encode;
   DecodeFunction decode;
};
FunctionPair g_Functions[] = {
   { MyEncode1, MyDecode1 },
   { MySuperEncode, MySuperDecode },
   { MyTurboEncode, MyTurboDecode },
};

Qu'est-ce qui est "laid"? ou "difficile à maintenir" dans l'approche ci-dessus?

Un objet avec une méthode operator () définie peut ressembler beaucoup à une fonction mais être généralement plus agréable à utiliser.

Le polymorphisme pourrait faire l'affaire: vous pourriez suivre le modèle de stratégie en tenant compte de chaque stratégie pour implémenter une de vos fonctions (ou une paire).

Créez ensuite un vecteur de stratégies et utilisez celui-ci à la place de la liste de fonctions.

Mais franchement, je ne vois pas le problème avec le tableau de fonctions; vous pouvez facilement créer un typedef pour faciliter la lisibilité. Effectivement, vous utiliserez exactement la même structure de fichier lorsque vous utiliserez le modèle de stratégie.

// functiontype.h
typedef bool (*forwardfunction)( double*, double* );

// f1.h
#include "functiontype.h"
bool f1( double*, double* );

// f1.c
#include "functiontype.h"
#include "f1.h"
bool f1( double* p1, double* p2 ) { return false; }


// functioncontainer.c    
#include "functiontype.h"
#include "f1.h"
#include "f2.h"
#include "f3.h"

forwardfunction my_functions[] = { f1, f2, f3 };
  • La déclaration de fonction et les définitions sont dans des fichiers séparés - le temps de compilation est correct.
  • Le groupe de fonctions est dans un fichier séparé, dépendant uniquement des déclarations

Vous pouvez consulter la bibliothèque Boost.Signals . Je crois qu’il a la possibilité d’appeler ses fonctions enregistrées à l’aide d’un index.

Essayez la classe Loki :: Functor. Plus d'informations sur CodeProject.com

Vous devez utiliser un tableau de pointeurs de fonction. Le seul problème est que toutes les fonctions doivent avoir fondamentalement le même prototype, seul le nom de la fonction et les noms des arguments passés peuvent varier. Le type de retour et les types d'argument (ainsi que le nombre d'arguments et d'ordre) doivent être identiques.

int Proto1( void );
int Proto2( void );
int Proto3( void );

int (*functinPointer[3])( void ) =
{
   Proto1,
   Proto2,
   Proto3
};

Ensuite, vous pouvez faire quelque chose comme ceci:

int iFuncIdx = 0;
int iRetCode = functinPointer[iFuncIdx++]();

Si vous avez regardé dans la bibliothèque boost :: signaux , vous verrez un exemple très joli, très élégant:
Supposons que vous ayez 4 fonctions comme:

void print_sum(float x, float y)
{
  std::cout << "The sum is " << x+y << std::endl;
}

void print_product(float x, float y)
{
  std::cout << "The product is " << x*y << std::endl;
}

void print_difference(float x, float y)
{
  std::cout << "The difference is " << x-y << std::endl;
}

void print_quotient(float x, float y)
{
  std::cout << "The quotient is " << x/y << std::endl;
}

Ensuite, si vous souhaitez les appeler de manière élégante, essayez:

boost::signal<void (float, float)> sig;

sig.connect(&print_sum);
sig.connect(&print_product);
sig.connect(&print_difference);
sig.connect(&print_quotient);

sig(5, 3);

Et le résultat est:

The sum is 8
The product is 15
The difference is 2
The quotient is 1.66667
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top