2012-06-03 26 views
7

Qualcuno può spiegare perché il risultato del codice seguente sarebbe "classe B :: 1"?esegue il metodo della classe derivata, ma ottiene il parametro predefinito dal metodo della classe base

Perché il metodo virtuale della classe derivata utilizza il parametro predefinito di una classe base e non il proprio? Per me è abbastanza strano. Grazie in anticipo!

Codice:

#include <iostream> 

using namespace std; 

class A 
{ 
public: 
    virtual void func(int a = 1) 
    { 
     cout << "class A::" << a; 
    } 
}; 

class B : public A 
{ 
public: 
    virtual void func(int a = 2) 
    { 
     cout << "class B::" << a; 
    } 
}; 

int main() 
{ 
    A * a = new B; 
    a->func(); 

    return 0; 
} 

risposta

6

Poiché gli argomenti predefiniti vengono risolti in base al tipo statico di this (ovvero, il tipo della variabile stessa, ad esempio A& in A& a;).

Modificare il vostro esempio un po ':

#include <iostream> 

class A 
{ 
public: 
    virtual void func(int a = 1) 
    { 
     std::cout << "class A::" << a << "\n"; 
    } 
}; 

class B : public A 
{ 
public: 
    virtual void func(int a = 2) 
    { 
     std::cout << "class B::" << a << "\n"; 
    } 
}; 

void func(A& a) { a.func(); } 

int main() 
{ 
    B b; 
    func(b); 
    b.func(); 

    return 0; 
} 

osserviamo il seguente output:

class B::1 
class B::2 

in azione a ideone.

Non è consigliabile che una funzione virtuale modifichi il valore predefinito per questo motivo. Sfortunatamente non conosco alcun compilatore che avvisi su questo costrutto.


La spiegazione tecnica è che ci sono due modi di trattare con argomento di default:

  • creare una nuova funzione di agire come trampolino: void A::func() { func(1); }
  • aggiuntivo l'argomento mancante alla chiamata sito a.func() =>a.func(/*magic*/1)

Se fosse il primo (e supponendo che il A::func w come dichiarato virtual, quindi funzionerebbe come ci si aspetta. Tuttavia, la seconda forma è stata eletta, sia perché i problemi con virtual non erano previsti al momento o perché sono stati considerati irrilevanti di fronte ai benefici (se del caso ...).

5

Poiché il valore predefinito viene sostituito durante la compilazione ed è tratto da dichiarazione, mentre la funzione reale di essere chiamato (A :: func o B :: func) è determinato in fase di esecuzione.

+0

Grazie per la risposta veloce! – Aremyst

5

Poiché il polimorfismo in C++ ha effetto in fase di esecuzione, mentre la sostituzione dei parametri predefiniti ha effetto in fase di compilazione. Al momento della compilazione, il compilatore non sa (e non dovrebbe sapere) il tipo dinamico dell'oggetto a cui puntano i punti a. Quindi, prende l'argomento predefinito per l'unico tipo che conosce per a, che nel tuo esempio è A *.

(Questo è tra l'altro anche il motivo di default dei parametri sono riportati nella interfacce/intestazioni piuttosto che nelle implementazioni/definizioni. Il compilatore non inserisce il parametro predefinito in codice macchina della realizzazione, ma solo nel codice macchina del chiamante. Tecnicamente , il parametro predefinito è la proprietà del chiamante e il chiamante non conosce e non dovrebbe conoscere il tipo dinamico di un oggetto)

+0

La tua risposta è molto chiara, grazie! – Aremyst

Problemi correlati