2010-02-28 12 views
21

di recente ho scoperto che in C++ è possibile sovraccaricare l'operatore di "chiamata di funzione", in un modo strano in cui si deve scrivere due coppie di parentesi di farlo:Come può essere utile sovraccaricare l'operatore "chiamata di funzione"?

class A { 
    int n; 
public: 
    void operator()() const; 
}; 

E poi usarlo in questo modo:

A a; 
a(); 

Quando è utile?

+3

Leggi informazioni sugli oggetti funzione. http://en.wikipedia.org/wiki/Function_object – AnT

risposta

27

questo può essere usato per creare "functors", oggetti che si comportano come funzioni:

class Multiplier { 
public: 
    Multiplier(int m): multiplier(m) {} 
    int operator()(int x) { return multiplier * x; } 
private: 
    int multiplier; 
}; 

Multiplier m(5); 
cout << m(4) << endl; 

Le stampe sopra 20. L'articolo di Wikipedia sopra riportato fornisce esempi più sostanziali.

+3

E il motivo principale per cui si vogliono i functor è avere funzioni di ordine superiore in C++. –

+1

È possibile espandere questo ad esempio, moltiplicare per m la prima volta che lo si chiama, moltiplicare per m + 1 la seconda volta, ecc. Le funzioni normali non possono salvare alcuna informazione di stato tra le chiamate, ma i funtori possono. – MatrixFrog

+3

Bene puoi sempre usare le variabili statiche in una funzione per dargli lo stato (o globals - shudder). Ma entrambi sono molto brutti e inclini all'errore. (Io userei invece un funtore .. ma è possibile) –

1

Se si sta creando una classe che incapsula un puntatore a funzione, ciò potrebbe rendere l'utilizzo più ovvio.

4

Un algoritmo implementato utilizzando un modello non interessa se la cosa chiamata è una funzione o un functor, si preoccupa della sintassi. O quelli standard (ad es. For_each()) o i tuoi. E i funtori possono avere lo stato e fare ogni genere di cose quando vengono chiamati. Le funzioni possono avere solo lo stato con una variabile locale statica o variabili globali.

15

C'è poco più di un guadagno sintattico nell'uso dell'operatore() finché non si inizia a utilizzare i modelli. Ma quando si usano i modelli è possibile trattare le funzioni reali e i funtori (le classi agiscono come funzioni) allo stesso modo.

class scaled_sine 
{ 
    explicit scaled_sine(float _m) : m(_m) {} 
    float operator()(float x) const { return sin(m*x); } 
    float m; 
}; 

template<typename T> 
float evaluate_at(float x, const T& fn) 
{ 
    return fn(x); 
} 

evaluate_at(1.0, cos); 
evaluate_at(1.0, scaled_sine(3.0)); 
+0

Sì; gli oggetti funzione-come sono davvero utili quando si ha una digitazione sufficientemente debole. Il C++ non lo ha capito, ma i template lo fanno. –

+0

Penso al costruttore di scaled_sine. –

0

Il compilatore può anche inline il funtore e la chiamata di funzione. Tuttavia, non è in grado di allineare un puntatore a funzione. In questo modo, l'utilizzo dell'operatore di chiamata di funzione può migliorare significativamente le prestazioni quando viene utilizzato, ad esempio, con gli algoritmi di liberia C++ standard.

Problemi correlati