2013-04-05 1 views
17

Nella mia classe chiamata Mat, voglio avere una funzione che prende un'altra funzione come parametro. In questo momento ho le 4 funzioni di seguito, ma ottengo un errore quando si chiama print(). La seconda riga mi dà un errore, ma non capisco perché, dal momento che il primo funziona. L'unica differenza è la funzione f non è un membro della classe Mat, ma è f2. Il fallimento è: error: no matching function for call to Mat::test(< unresolved overloaded function type>, int)'C++ - <tipo funzione sovraccarico non risolto>

template <typename F> 
int Mat::test(F f, int v){ 
    return f(v); 
} 

int Mat::f2(int x){ 
    return x*x; 
} 

int f(int x){ 
    return x*x; 
} 

void Mat::print(){ 
    printf("%d\n",test(f ,5)); // works 
    printf("%d\n",test(f2 ,5)); // does not work 
} 

Perché accade questo?

+1

È 'f2' statico o no? –

+0

Provare a cambiare la chiamata printf a printf ("% d \ n", test (Mat :: f2, 5)); – 2to1mux

+0

Avete più di un sovraccarico di 'f2'? –

risposta

3

Il problema qui è che f2 è un metodo su Mat, mentre f è solo una funzione gratuita. Non è possibile chiamare da solo f2, ma è necessario richiamare l'istanza di Mat. Il modo più semplice intorno a questo potrebbe essere:

printf("%d\n", test([=](int v){return this->f2(v);}, 5)); 

Il = vi catturerà this, che è ciò che è necessario chiamare f2.

+0

Poiché f2 e stampa sono entrambe funzioni membro di Mat, non è consentito stampare per chiamare f2 senza fare riferimento a un oggetto Mat? – 2to1mux

+0

Wow, funziona (con alcune modifiche dal codice originale). +1 da me –

+0

-1. il messaggio di errore indica che l'errore si verifica a causa di una funzione sovraccaricata e non perché la sintassi della chiamata della funzione del modello di funzione è errata (che è ciò che si dice). –

31

Il tipo di pointer-to-member-function è diverso da pointer-to-function.

Il tipo di una funzione è diversa a seconda se si tratta di una funzione ordinaria o una funzione membro non statica di una classe:

int f(int x); 
the type is "int (*)(int)" // since it is an ordinary function 

E

int Mat::f2(int x); 
the type is "int (Mat::*)(int)" // since it is a non-static member function of class Mat 

Nota: se è una funzione membro statico della classe Fred, il suo tipo è lo stesso di una normale funzione: "int (*)(char,float)"

In C++, member functions have an implicit parameter which points to the object (the this pointer inside the member function). Normal C functions can be thought of as having a different calling convention from member functions, so the types of their pointers (pointer-to-member-function vs pointer-to-function) are different and incompatible. C++ introduces a new type of pointer, called a pointer-to-member, which can be invoked only by providing an object.

NOTE: do not attempt to "cast" a pointer-to-member-function into a pointer-to-function; the result is undefined and probably disastrous. E.g., a pointer-to-member-function is not required to contain the machine address of the appropriate function. As was said in the last example, if you have a pointer to a regular C function, use either a top-level (non-member) function, or a static (class) member function.

Ulteriori informazioni su questo Here e here.

+0

Ma questo non spiega perché il modello non posso risolverlo O mi sta sfuggendo qualcosa? –

+0

@LuchianGrigore Ecco come l'ho capito. Il compilatore si aspetta un tipo che fornisce un 'operatore di chiamata' o vede se riesce a trovare una funzione che corrisponda a' int f (int) 'raggiungibile da Mat :: Test. E secondo la descrizione di cui sopra 'funzione puntatore-membro-funzione vs puntatore-a-funzione sono diversi e incompatibili'. Quindi non corrisponderà a 'this-> f2' come funzione. Questa è solo la mia comprensione. Non lo sapevo nemmeno prima di oggi :) –

+0

I link sembrano morti. – derM