2017-01-04 4 views
1

J'ai ce code qui utilise un pointeur de fonction au point 3 fonctions somme, soustraire, mul. Ça marche bien. mais maintenant le problème est que j'ai des fonctions avec différents no.of paramètres et différents types de données. comment mettre en œuvre cela.pointeur de fonction pour différentes fonctions avec différents types de données ou paramètre

int add(int a, int b) 
{ 
    cout<<a+b; 
} 
int subtract(int a, int b) 
{ 
    cout<<a-b; 
} 
int mul(int a, int b) 
{ 
    cout<<a*b; 
} 

int main() 
{ 

    int (*fun_ptr_arr[])(int, int) = {add, subtract, mul}; 
    unsigned int ch, a = 15, b = 10,c=9; 
    ch=2; 
    if (ch > 4) return 0; 

    (*fun_ptr_arr[ch])(a, b); 

    return 0; 
} 
+0

Side note, vous devez vérifier 'ch> 2', pas' ch> 4' (ou mieux encore, 'ch> sizeof (fun_ptr_arr)/sizeof (* fun_ptr_arr) -1'). –

Répondre

0

La réponse simple est que techniquement, vous ne pouvez pas faire cela. Vous pourriez faire quelques manipulations en utilisant un tableau comme entrée pour toutes ces fonctions, mais vous devrez toujours savoir exactement ce qu'il faut passer à chaque fonction. Du point de vue de l'ingénierie logicielle, vous ne devriez pas le faire - je vous suggère de jeter un coup d'œil les réponses bien ici: C++ Function pointers with unknown number of arguments

0

Si vous avez les fonctions suivantes

int f1(int i); 
int f2(int i, int j); 

Vous pouvez définir un type de fonction générique comme ce

typedef int (*generic_fp)(void); 

Et puis initialiser votre tableau de fonction

generic_fp func_arr[2] = { 
    (generic_fp) f1, 
    (generic_fp) f2 
}; 

Mais vous devrez jeter les fonctions de back

int result_f1 = ((f1) func_arr[0]) (2); 
int result_f2 = ((f2) func_arr[1]) (1, 2); 

De toute évidence, il ne ressemble pas à une bonne façon de construire un programme

Pour rendre le code semble un peu mieux que vous pouvez définir des macros

#define F1(f, p1) ((f1)(f))(p1) 
#define F2(f, p1, p2) ((f2)(f))(p1, p2) 

int result_f1 = F1(func_arr[0], 2); 
int result_f2 = F2(func_arr[1], 1, 2); 

EDIT

oublié de mentionner, vous devez également définir un type pour chaque type de fonction

typedef int (*fi)(int); // type for function of one int param 
typedef int (*fii)(int, int); // type for function of two int params 

Et ensuite coulé stockées des pointeurs vers ces types

int result_f1 = ((fi) func_arr[0]) (2); 
int result_f2 = ((fii) func_arr[1]) (1, 2); 

Voici un exemple complet

#include <iostream> 

typedef int (*generic_fp)(void); 
typedef int (*fi)(int); // type for function of one int param 
typedef int (*fii)(int, int); // type for function of two int params 

#define F1(f, p1) ((fi)(f))(p1) 
#define F2(f, p1, p2) ((fii)(f))(p1, p2) 

int f1(int i); 
int f2(int i, int j); 

int main() 
{ 

    generic_fp func_arr[2] = { 
     (generic_fp) f1, 
     (generic_fp) f2 
    }; 

    int result_f1_no_macro = ((fi) func_arr[0]) (2); 
    int result_f2_no_macro = ((fii) func_arr[1]) (1, 2); 


    int result_f1_macro = F1(func_arr[0], 2); 
    int result_f2_macro = F2(func_arr[1], 1, 2); 

    std::cout << result_f1_no_macro << ", " << result_f2_no_macro << std::endl; 
    std::cout << result_f1_macro << ", " << result_f2_macro << std::endl; 

    return 0; 
} 

int f1(int i) 
{ 
    return i * 2; 
} 

int f2(int i, int j) 
{ 
    return i + j; 
} 

Le code ci-dessus produit la sortie suivante

4, 3 
4, 3 
+0

erreur se produit dans cette ligne int result_f1 = ((f1) func_arr [0]) (2); int résultat_f2 = ((f2) fonc_arr [1]) (1, 2); –

0

A légèrement différent approche nt utilisant des objets pour implémenter le comportement requis. Afin d'avoir une solution vraiment générique, nous devons utiliser Interfaces. Démonter les données et le fonctionnement, c'est-à-dire les conserver séparément. Maintenant, chaque opération connaît le type de données sur lequel elle fonctionne et n'attendra que ce type de données.

struct Operation_Add : public IOperation 
{ 
      //data for operation addition. 
      struct Data : public IData 
      { 
        int a; 
        int b; 
        int result; 
      }; 

      IData* Execute(IData *_pData) 
      { 
        //expected data is "Operation_Add::Data_Add" 
        Operation_Add::Data *pData = dynamic_cast<Operation_Add::Data*>(_pData); 
        if(pData == NULL) 
        { 
          return NULL; 
        } 

        pData->result = pData->a + pData->b; 
        return pData; 
      } 
}; 

struct Operation_Avg : public IOperation 
{ 
      //data for operation average of numbers. 
      struct Data : public IData 
      { 
        int a[5]; 
        int total_numbers; 
        float result; 
      }; 

      IData* Execute(IData *_pData) 
      { 
        //expected data is "Operation_Avg::Data_Avg" 
        Operation_Avg::Data *pData = dynamic_cast<Operation_Avg::Data*>(_pData); 
        if(pData == NULL) 
        { 
          return NULL; 
        } 

        pData->result = 0.0f; 
        for(int i = 0; i < pData->total_numbers; ++i) 
        { 
          pData->result += pData->a[i]; 
        } 
        pData->result /= pData->total_numbers; 
        return pData; 
      } 
}; 

Ici, est le processeur d'opération, le CPU.

struct CPU 
{ 
      enum OPERATION 
      { 
        ADDITION = 0, 
        AVERAGE 
      }; 

      Operation_Add m_stAdditionOperation; 
      Operation_Avg m_stAverageOperation; 
      map<CPU::OPERATION, IOperation*> Operation; 

      CPU() 
      { 
        Operation[CPU::ADDITION] = &m_stAdditionOperation; 
        Operation[CPU::AVERAGE] = &m_stAverageOperation; 
      } 
}; 

Exemple:

CPU g_oCPU; 

    Operation_Add::Data stAdditionData; 
    stAdditionData.a = 10; 
    stAdditionData.b = 20; 

    Operation_Avg::Data stAverageData; 
    stAverageData.total_numbers = 5; 
    for(int i = 0; i < stAverageData.total_numbers; ++i) 
    { 
      stAverageData.a[i] = i*10; 
    } 

    Operation_Add::Data *pResultAdd = dynamic_cast<Operation_Add::Data*>(g_oCPU.Operation[CPU::ADDITION]->Execute(&stAdditionData)); 
    if(pResultAdd != NULL) 
    { 
      printf("add = %d\n", pResultAdd->result); 
    } 

    Operation_Avg::Data *pResultAvg = dynamic_cast<Operation_Avg::Data*>(g_oCPU.Operation[CPU::AVERAGE]->Execute(&stAverageData)); 
    if(pResultAvg != NULL) 
    { 
      printf("avg = %f\n", pResultAvg->result); 
    }