2010-06-16 13 views
18

Me hicieron esta loca pregunta. Estaba fuera de mi ingenio.Pregunta de la entrevista sobre funciones virtuales en C++

¿Se puede llamar a un método en la clase base que se declara como virtual utilizando el puntero de clase base que apunta a un objeto de clase derivado?

¿Esto es posible?

+9

Es posible que desee obtener uno de los libros introductorios de [The Definitive C++ Book Guide and List] (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). –

+2

@James: Creo que él está preguntando si puedes llamar 'base :: foo()' no 'derived :: foo()' usando 'p' si' p' es 'base *' y apunta a un 'derivado ' –

+0

@John: ¿Entonces? James tiene razón, sin embargo. – sbi

Respuesta

49

Si está intentando invocar un método virtual desde el puntero de la clase base, sí.

Eso es polimorfismo.

Si está preguntando, con un puntero de clase base a una clase derivada, ¿puede invocar un método de clase base que sea anulado por la clase derivada? Sí que es también posible gracias a la determinación del alcance explícitamente el nombre de clase base:

basePtr->BaseClass::myMethod();

+4

El polimorfismo es donde clasifica el método de clase derivado porque el método es virtual en la clase base. En realidad, llamar al método de la clase base por medio de un puntero a la base, incluso si el método de la clase base ha sido anulado, pasa por alto el polimorfismo, que es diferente. –

+1

En realidad es todo lo contrario. La pregunta es pedir llamar al método virtual de la clase base cuando el objeto es del tipo derivado que anula el método. – JaredPar

+5

Hrm, la pregunta tal como estaba escrita era confusa. – Alan

10

¿Quieres decir algo como esto. (Donde pBase es de tipo puntero a base, pero la punta-a-objeto es en realidad de tipo Derived que se deriva de Base.)

pBase->Base::method(); 

sí, es posible.

16

Probar:

class A   { virtual void foo(); } 
class B : public A { virtual void foo(); } 

A *b = new B(); 
b->A::foo(); 
+4

En realidad, creo que debería ser "A * b = new B()", en lugar de "B * b = new B()", para seguir la pregunta. – Luca

+1

Sí, debería. –

-1

No. No de una manera limpia. Pero si. Tienes que hacer algo de manipulación del puntero, obtener un puntero al vtable y hacer una llamada. pero eso no es exactamente un puntero a la clase base, sino una manipulación inteligente del puntero. Otro enfoque es usar el operador de resolución de alcance en la clase base.

+0

C++ soporta directamente lo que la pregunta plantea. 'base-> base :: function()' haría el truco. No es necesario hackear vtable aquí. –

+2

Vuelve a leer tu publicación. "operador de resolución de alcance" no es "otro enfoque". Es el único enfoque que deberías considerar. –

+0

Estoy de acuerdo. La resolución del alcance es la forma .. –

10

Sí - usted tiene que especificar el nombre completo sin embargo:

#include <iostream> 

struct base { 
    virtual void print() { std::cout << "Base"; } 
}; 

struct derived : base { 
    virtual void print() { std::cout << "Derived"; } 
}; 

int main() { 
    base *b = new derived; 
    b->base::print(); 
    delete b; 
    return 0; 
} 
5

Si entiendo bien la pregunta, que tienen

class B 
{ 
public: 
    virtual void foo(); 
}; 

class D: public B 
{ 
public: 
    virtual void foo(); 
} 

B* b = new D; 

Y la pregunta es, ¿puede llamar B::foo().La respuesta es sí, utilizando

b->B::foo() 
0
class B 
{ 
public: 
    virtual void foo(); 
}; 

class D: public B 
{ 
public: 
    virtual void foo(); 
} 

B* b = new D; 

Intente llamar

(*b).foo() 

para invocar la función foo clase base

+0

¿está seguro de que esto llamará a la función de la clase base foo? ¿Lo has probado? – Vijay

+0

Mi hipótesis general era que (* b) eventualmente tendría el objeto adecuado, pero en la compilación y ejecución encontré que este no es el caso. Aún llama a la función derivada. Esto me ha creado confusión también, ¿cuál es la diferencia entre (* b) .foo() y B b1 = * b; b1.foo() – Pardeep

0
class B { 
    public: virtual void foo(); 
}; 

class D: public B { 
    public: virtual void foo() 
    { 
     B::foo(); 
    }; 
} 

B* b = new D; 

Soluciones:

  1. b->foo();
  2. b->B::foo()

  3. O no anulan/definir foo() en la clase D derivada y llamar b-> foo()

  4. B objb = *b; objb.foo() ; // this is object slicing and not (*b).foo() as in one of the previous answers

Cuestiones relacionadas