2010-01-14 15 views
12

Deve essere qualcosa di specifico nel mio codice, che non posso pubblicare. Ma forse qualcuno può suggerire possibili cause.Il metodo C++ è visibile solo quando si esegue il cast dell'oggetto nella classe base?

Fondamentalmente ho:

class CParent 
{ 
public: 
    void doIt(int x); 
}; 
class CChild : public CParent 
{ 
public: 
    void doIt(int x,int y,int z); 
}; 

CChild *pChild = ... 
pChild->doIt(123); //FAILS compiler, no method found 
CParent *pParent = pChild; 
pParent->doIt(123); //works fine 

Come sulla terra?

EDIT: le persone parlano di ombre/nascondigli. Ma le due versioni di do hanno un numero diverso di parametri. Sicuramente questo non può confondere il compilatore, sovraccarichi in classe figlio che non possono essere confusi con la versione della classe genitore? Può esso?

L'errore del compilatore che ottengo è: errore C2660: 'CChild :: doIt': la funzione non accetta 1 argomento

+0

Wow. Non c'è molto da fare ... –

+1

Sono sorpreso che tu stia vedendo qualsiasi metodo. –

+0

in fondo ho ... niente? –

risposta

29

Hai ombra di un metodo. Per esempio:

struct base 
{ 
    void method(int); 
    void method(float); 
}; 

struct derived : base 
{ 
    void method(int); 
    // base::method(int) is not visible. 
    // base::method(float) is not visible. 
}; 

È possibile risolvere questo con una direttiva using:

class derived : public base 
{ 
    using base::method; // bring all of them in. 

    void method(int); 
    // base::method(int) is not visible. 
    // base::method(float) is visible. 
}; 

Dal momento che sembra insistente circa il numero di parametri, mi rivolgo a questo. Ciò non cambia nulla. Osservare:

struct base 
{ 
    void method(int){} 
}; 

struct derived : base 
{ 
    void method(int,int){} 
    // method(int) is not visible. 
}; 

struct derived_fixed : base 
{ 
    using base::method; 
    void method(int,int){} 
}; 

int main(void) 
{ 
    { 
     derived d; 

     d.method(1, 2); // will compile 
     d.method(3); // will NOT compile 
    } 
    { 
     derived_fixed d; 

     d.method(1, 2); // will compile 
     d.method(3); // will compile 
    } 
} 

Sarà ancora essere scura indipendentemente parametri o tipi restituiti; è semplicemente il nome che ombre. using base::<x>; porterà in visibilità tutti i metodi "<x>" di base.

+0

Fantastico, non pensavo che avrei ancora scoperto strane funzionalità di C++. –

+2

La direttiva using non porterà tutti i metodi della classe base in visibilità. Bene, in questo caso sì, ma in generale. Porterà in visibilità tutti i metodi con il nome indicato nella direttiva using. È pignolo di me, sì. Ma è una distinzione importante. – Omnifarious

+0

Vero, lascia che ti dia una risposta. – GManNickG

0

Il problema è CChild in realtà non ereditare da CParent.

E quindi non ha un metodo doIt che richiede solo un argomento.

+0

typo. risolto. = ora. –

-2

Il metodo nella classe figlia ha un numero diverso di argomenti rispetto a quello che si sta tentando di trasmettere. Potrebbe essere collegato a questo?

2

Stai riscontrando un problema classico. Hai bisogno di using CParent::doIt; nella tua classe CChild. Scriverò le domande doppie.

Edit:

Ecco la mia risposta essenzialmente la stessa domanda: Overriding a Base's Overloaded Function in C++

+0

Cosa? Il sovraccarico nella classe figlio ha parametri diversi rispetto alla classe genitore. Perché dovrebbe essere un problema? –

+0

Leggi la risposta collegata. Penso che spiegherà le cose. –

+0

Tutti gli esempi pubblicati sono per sovraccarichi con lo stesso numero di argomenti. Posso vedere quelli che confondono il compilatore. Ma quando vede doit (123), e trova doIt (x, y, z), perché dovrebbe trattarlo come una corrispondenza e smettere di guardare? –

1

Non l'ho mai fatto senza avere quel metodo nella classe base prima. Penso che aggiungere "using CLASS :: METHOD" nella classe derivata ti darà accesso all'altra versione del metodo overload.

class CParent 
{ 
public: 
    void doIt(int x); 
}; 
class CChild : public CParent 
{ 
public: 
    void doIt(int x,int y,int z); 

    using CParent::doIt; 
}; 
0

Quando si ignora una funzione nella classe derivata, ma solo che la funzione nella classe derivata è visibile all'utente di quella classe. La versione della classe base diventa nascosta.

Pertanto, il puntatore pChild che chiama doIt (int x) avrà esito negativo poiché si sta utilizzando un puntatore classe derivato per chiamare la funzione della classe base. Il puntatore pParent che chiama doIt (int x) funzionerà dato che stai usando un puntatore di classe base per chiamare la funzione della classe base. Anche se si ha un oggetto figlio puntato da un puntatore genitore (upcasted), il tipo di classe qui è determinato dalla dichiarazione del puntatore che è un CParent.

Per essere in grado di chiamare quella funzione della classe di base utilizzando il puntatore di classe derivata, è possibile:

  1. qualificare il nome della classe base nella chiamata di funzione, come nell'esempio seguente:

    pChild->CParent::doIt(123);

  2. Utilizzare una direttiva using per portare il nome della funzione dalla classe base nella classe derivata, come si vede nei post precedenti.

0

Capisco che questo comportamento è quello di dare flessibilità per ignorare il comportamento del metodo della classe base nella classe derivata.

Supponiamo di avere una funzione foo (int) nella classe base e di voler modificare il comportamento di questa funzione nella classe derivata. Ora se il metodo della classe base non è nascosto dal metodo della classe derivata (che ha lo stesso prototipo di quello del metodo della classe base), introdurrà ambiguità nella risoluzione di sovraccarico.

Problemi correlati