2011-12-29 10 views
5

Sono perplesso dal motivo per cui la dichiarazione di void operator()(int) nella classe base nell'esempio di codice sottostante è apparentemente nascosta quando la classe derivata implementa void operator()(int,int,int). Come posso ottenere la dichiarazione di operator() (int) dalla classe base foo per essere visibile nella classe derivata bar? Cioè, come posso modificare l'esempio in modo che l'invocazione di operator() (int) funzioni?Ereditarietà dell'operatore()

#include <iostream> 

struct foo 
{ 
     void operator()(int) 
     { 
       std::cout << "A" << std::endl; 
     } 
}; 

struct bar : foo 
{ 
     // If this is uncommented, the code will not compile. 
     // void operator()(int, int, int) {} 
}; 

int main() 
{ 
     bar b; 
     b(1); 
     return 0; 
} 

quando si compila con g ++ con le linee marcate senza commenti, il messaggio di errore è sulla falsariga di "non può competere con chiamata a 'bar (int)' ... candidato è il bar vuoto :: operator() (int, int, int) ... candidato si aspetta 3 argomenti, 1 fornito. "

risposta

6

Proprio così. Le funzioni di classe derivate nascondono le funzioni di classe base piuttosto che l'overload. La soluzione è piuttosto semplice:

struct bar : foo 
{ 
    using foo::operator(); 
    void operator()(int, int, int) {} 
}; 
+0

Grazie per la risposta! Potresti spiegare perché la dichiarazione d'uso è necessaria in questo caso? Non vedo come dichiarando operator() (int, int, int) dovrebbe eclissare la dichiarazione di operator() (int) nella classe base. Dover specificare la parola chiave using è un po 'macchinoso, dato che in uno scenario del mondo reale, dovrei aggiungere questo ad ogni classe base. –

+4

Perché? Perché lo standard dice così. "Un nome può essere nascosto da una dichiarazione esplicita dello stesso nome in una regione dichiarativa nidificata o in una classe derivata." Vedi anche: http://www2.research.att.com/~bs/bs_faq2.html#overloaderived –

+0

In realtà, l'override delle funzioni virtuali nasconde anche le funzioni della classe base. Ciò è particolarmente fastidioso quando una classe base ha più funzioni virtuali pubbliche che sono sovraccarichi con lo stesso nome: quando si esegue l'override di una di queste, tutte le altre sono nascoste! Questo è uno dei motivi per cui la libreria standard C++ non ha alcuna funzione pubblica virtuale (eccetto per i distruttori che non possono essere sovraccaricati in ogni caso e funzionano in qualche modo in modo diverso rispetto alla sovrascrittura in ogni caso). Invece, le funzioni pubbliche delegano alle funzioni virtuali protette (dovrebbero essere private). –

2

Si noti che l'operatore() potrebbe rendere questo aspetto più confuso di quanto non sia. L'esempio classico sarebbe probabilmente qualcosa di più simile a bar :: mymethod (int) e foo :: mymethod(). Il metodo derivato nasconde il metodo ereditato a causa di come avviene la risoluzione. La dichiarazione d'uso spiegata in un'altra risposta introduce il metodo di risoluzione di foo.