2012-01-11 23 views
10

Estoy probando con palabras clave virtuales y conceptos de herencia en C++. He escrito un pequeño programa:Sobrecarga de una función virtual en una clase secundaria

#include<stdio.h> 
#include<iostream> 

using namespace std; 

class cna_MO 
{ 
    public: 
    virtual void print() 
    { 
     cout << "cna_MO" << endl; 
    } 
}; 

class cna_bsc:public cna_MO 
{ 
    public: 
    void print() 
    { 
     cna_MO::print(); 
    } 

    void print(int a) 
    { 
     cout << "cna_BSC" << endl; 
    } 
}; 

class cna_Mo 
{ 
    cna_MO *_mo; 

    public: 
    cna_Mo() 
    { 
     _mo = new cna_bsc; 
    } 

    virtual void print(int a) 
    { 
     cout << "cna_Mo with arg" << endl; 
     _mo->print(5); 
    } 

    virtual void print() 
    { 
     cout << "cna_Mo" << endl; 
     _mo->print(); 
    } 
}; 

int main() 
{ 
    cna_Mo valid_mo; 
    cout << "old case is started" << endl; 
    valid_mo.print(); 
    cout << "new case is started" << endl; 
    valid_mo.print(5); 
    return 0; 
} 

Lo que he hecho aquí es que he sobrecargado una función virtual en la clase padre en la clase de niño! ¿No es esto lo correcto?

estoy consiguiendo los errores de compilación de la siguiente manera:

"temp10.cc", line 45: Error: Too many arguments in call to "cna_MO::print()".

+1

Si realmente necesita 'stdio' (no es necesario en el código que proporcionó), [debe incluir' cstdio' en lugar de 'stdio.h'] (http://stackoverflow.com/questions/301586/what-is-the-difference-between-using-includefilename-and-includefilename-h). –

+0

Además, nunca elimina el puntero que asigna en el constructor cna_Mo. –

Respuesta

23

Una vez que la sobrecarga de una función de la clase Base en clase derivada todas las funciones con el mismo nombre en la clase Base quedan ocultos en la clase derivada.

Una vez que haya agregado la función cna_bsc::print(int a) a su clase derivada, la función cna_MO::::print() ya no será visible para los usuarios de la clase Derivada. Esto se conoce como ocultación de funciones.

Solución: Con el fin de hacer que la función oculta visible en clase derivada, es necesario agregar:

using cna_MO::print; 

en la sección public de su clase derivada cna_bsc.

Buena lectura:

What's the meaning of, Warning: Derived::f(char) hides Base::f(double)?

+0

Entiendo tu punto, pero aún tengo un problema más ... edité la pregunta. Por favor, revisa la pregunta ahora. Incluso después de hacer los cambios, estoy recibiendo demasiados errores de Agrs. – Vijay

+3

El error está en 'cna_MO :: print()' cuando llama a '_mo-> print (5);' observe que '_mo' es del tipo' cna_MO * 'y' cna_MO' no tiene 'print() 'función que toma un solo argumento y por lo tanto el error. El motivo de su confusión es confundir nombres de clases no distintos, ** NO UTILICE NUNCA LA CONVENCIÓN DE NOMBRES COMO ESO ** –

0

Se debe a que la función de impresión en la clase de niño toma un parámetro y el original no lo hace.

en cna_MO (clase padre):

virtual void print() 

en cna_bsc (clase hija):

void print(int a) 

Básicamente impresión de que el niño no debería tener un argumento int:

void print() 

EDITAR:

¿Quizás lo mejor sería hacer pasar el int opcional?

por ejemplo:

en cna_MO (clase padre):

virtual void print(int a=-1) { 
    if (a == -1) { 
     // Do something for default param 
    } else { 
     cout << a; 
    } 
} 

en cna_bsc (clase hija):

void print(int a=-1) 

por lo que si a == -1 es probable que pueda suponer, ellos no pasaron nada

El truco es que tanto el padre como el hijo necesitan el mismo método siganture, es decir, el mismo tipo de devolución y los mismos tipos de argumento.

+0

Consulte la pregunta editada – Vijay

+0

Ahora es porque está intentando llamar pasando una int en esa línea: ' valid_mo.print (5); ' – matiu

0

Cuando tiene una función con el mismo nombre y diferentes parámetros en la clase derivada que la de la clase base, entonces esa función será oculta. Puede encontrar más información here ..

se puede llamar a la función específica oculto llamando al igual que Base::hiddenFun();

+0

Consulte la pregunta editada – Vijay

0

que no pueden trabajar porque dado un cna_MO *, se puede ver en tiempo de compilación que el objeto puntiagudo no lo hace (necesariamente) tiene la sobrecarga int. Si apuntara a un objeto de clase base, _mo->print(5); realmente no tendría nada que llamar. También puede haber un número infinito de clases derivadas (aún no implementadas) que no tienen que admitir esta llamada.

  1. Cada clase derivada debe tener print(int) - declarar que en la clase base.

  2. Cada clase derivada no necesita tener print(int)-cna_Mo sólo funciona con cna_bsc, por lo que el miembro debe ser cna_bsc* _mo.

0

Lo ideal sería que la impresión que se lleva a un int debe tener un nombre diferente pero teniendo en cuenta que desea ambas funciones a ser llamadas de impresión, debe hacer que los dos no virtual y hacer que se llaman funciones virtuales protegidas.

class cna_MO 
{ 
    public:  
    void print() { doPrint(); } 

    protected: 
    virtual void doPrint() 
     {   cout << "cna_MO" << endl;  
     } 
}; 


class cna_bsc:public cna_MO 
{ 
    protected:  
     virtual void doPrint() 
        // although with implementation no need to override it 
     {   
      cna_MO::print();  
     } 

    public: 
    void print(int a)  
     { 
      doPrintInt(a); 
     } 

    protected: 
     virtual void doPrintInt(int) 
     { 
     cout << "cna_BSC" << endl;  
     } 
}; 
0

Si realmente tiene que hacerlo de esta manera, es decir, tiene un puntero a una clase y como inicializar una clase derivada, no hay más remedio que echar siempre el puntero al tipo correcto cuando se la usa. En este caso, ((cna_bsc*)_mo)->print(5);

Cuestiones relacionadas