2008-09-24 13 views
1

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 en concevant ma disposition de code.Liste des fonctions C++

J'ai un certain nombre de fonctions que je veux pouvoir appeler par index. Plus précisément, je dois être en mesure d'en appeler un au hasard pour le processus de cryptage, mais ensuite l'adresser par un index spécifique dans le processus de décryptage.

Je considérais un tableau de fonctions classique, mais ma principale préoccupation est qu'un tableau de fonctions serait difficile à maintenir, et un peu moche. (Le but est d'obtenir chaque paire de fonctions dans un fichier séparé, afin de réduire les temps de compilation et faciliter la gestion du code.) Quelqu'un a-t-il une solution C++ plus élégante comme alternative à une matrice de fonctions? La vitesse n'est pas vraiment un problème, je suis plus préoccupé par la maintenabilité.

-Nicholas

Répondre

2

Vous pouvez é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 Run comme le nom de la fonction, si vous préférez.

0

un objet avec un procédé opérateur() définie peut agir un peu comme une fonction, mais généralement plus agréable à travailler.

5

Quel est le problème avec la fonction array?

Vous devez appeler des fonctions par index. Donc, ils doivent être mis dans une structure "indexable par index" en quelque sorte. Array est probablement la structure la plus simple qui répond à ce besoin.

Exemple (en tapant sur ma tête, pourrait ne pas compiler):

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

Qu'est-ce que « laid » ou « difficile à maintenir » dans l'approche ci-dessus?

0

Le polymorphisme pourrait faire l'affaire: vous pourriez suivre le modèle de stratégie, en considérant chaque stratégie pour mettre en œuvre une de vos fonctions (ou une paire d'entre eux). Puis créez un vecteur de stratégies, et utilisez celui-ci à la place de la liste des fonctions.

Mais franchement, je ne vois pas le problème avec la fonction tableau; vous pouvez facilement créer un typedef pour faciliter la lisibilité. Effectivement, vous obtiendrez exactement la même structure de fichier lors de l'utilisation du 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 - temps de compilation est ok.
  • Le groupement de fonction est dans un fichier séparé, ayant une dépendance aux déclarations que
0

Vous pouvez jeter un oeil à la Boost.Signals library. Je crois qu'il a la capacité d'appeler ses fonctions enregistrées en utilisant un index.

0

Si vous avez regardé dans la bibliothèque boost::signals, vous verrez un très bel exemple, qui est très élégant:
Supposons que vous avez 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 voulez les appeler de manière élégante essayer:

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 la sortie est:

The sum is 8 
The product is 15 
The difference is 2 
The quotient is 1.66667 
+0

Suggestion: utilisez le format 'exemple de code' pour des exemples de code. C'est le bouton ones-and-zéros dans l'éditeur de réponses. – jwfearn

0

Vous devez utiliser un tableau de pointeurs de fonction. Le seul hic, c'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++](); 
Questions connexes