2010-12-29 8 views
9
class B { 
virtual int foo(); 
}; 

class D : public B { 
virtual int foo() { cout<<"D\n"; } 
}; 

int B::foo() 
{ 
    /* how do i tell if this->foo() is overridden by a subclass, or if it will */ 
    /* simply recurse into B::foo()? */ 
    this->foo(); 
} 

main() 
{ 
D d; 
d.B::foo(); 
} 
+3

Probablemente no haya una manera confiable. ¿Por qué querrías? –

+0

Estoy de acuerdo con Oli- simplemente llame a d.foo() como una persona normal. – Puppy

+1

Quiero completar mi respuesta con algunos puntos de vista personales adicionales. Hago todo lo posible para nunca preguntarme por qué alguien quiere hacer algo. No puedo saber por qué quieren hacer algo, lo único que sé es que hicieron una pregunta.Creo que está bien tratar de resolver su problema Y proporcionar una alternativa que quizás no se les ocurra, pero las declaraciones como "hazlo como una persona normal" no son ni constructivas ni útiles. –

Respuesta

8

Respuesta: no se puede.

Expandiría si hubiera algo para expandir.

+0

eso es lo que yo también pensé. – deltamind106

0

La forma más segura es no anular foo() en absoluto, pero permitir la anulación de una función OnFoo() que se llama desde la clase base si no puede confiar en sus programadores. MFC hace mucho de esto para garantizar un comportamiento predeterminado (en lugar de proteger contra la recurrencia).

Luego, también en un nivel estático, todo lo que implementa OnFoo() se detecta fácilmente con un 'Buscar en archivos'.

E.g. (No probado para la sintaxis/compilación y no-hilo)

class B 
{ 
public: 
    B() 
    { 
     m_bInFoo=false; 
    } 

    int foo() 
    { 
     if(!m_bInFoo) 
     { 
      m_bInFoo=true; 

      int nRet = OnFoo(); 

      m_bInFoo=false; 

      return nRet; 
     } 

     return 0;// probably throw exception 
    } 

protected: 
    // inherited classes override OnFoo(), and never call OnFoo(); 
    virtual int OnFoo(){ return 0 }; 

private: 
    bool m_bInFoo; 
} 
1

siquiera me gusta la prestación de este .. pero aquí es

int B::foo() 
{ 
std::cout << "B" << std::endl; 
if (typeid (*this) != typeid(B)) 
    this->foo(); 
return 0; 
} 

Editar

Quiero demostrar que funciona en MSVC++ 2010.

#include "stdafx.h" 
#include <iostream> 

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

class D : public B { 
public: 
virtual int foo() { 
    std::cout<<"D\n"; return 0; 
} 
}; 

int B::foo() 
{ 
std::cout << "B" << std::endl; 

/* how do i tell if this->foo() is overridden by a subclass, or if it will */ 
/* simply recurse into B::foo()? */ 
if (typeid (*this) != typeid(B)) 
    this->foo(); 

return 0; 
} 


int main(int argc, _TCHAR* argv[]) 
{ 
D d; 
d.B::foo(); 

B b; 
b.foo(); 
return 0; 
} 

Ou tput

B 
D 
B 

prueba no siempre funcionará

Cambio D para esto y no va a funcionar más

class D : public B { }; 
+0

Eso no funciona. No está diciendo si foo() está anulado, y de hecho si no es su código recurrirá infinitamente en cualquier llamada a foo() en un objeto D; exactamente lo que el OP quiere evitar En realidad, no te ayuda a averiguar nada más allá de si el B en el que se invoca a foo() es en realidad una versión más específica o no ... eso es todo. Los puntos serían más significativos si la gente no se los entregara antes de verificar la validez de la respuesta. –

+0

@ Noah Roberts Tiene razón, si D no anula B :: foo, recurrirá. Esto también se puede resolver usando el desenrollamiento de la pila. Cree una variable en la pila que establece una bandera en el almacenamiento local de subprocesos una vez que ingrese B :: foo(), si B: foo() se ingresa nuevamente a través de la misma pila e intenta crear otra variable, puede verificar si la bandera se ha configurado y luego sale. Una vez que la pila se desenrolla, la destrucción de la variable puede desarmar la bandera. Mi solución resuelve el problema exacto que él dio, que es mi culpa ya que no leí en otros escenarios que podrían haber ocurrido. –

2

Un enfoque es hacer foo()función virtual pura en B, y también lo definen. De esta manera, asegúrese de que las clases derivadas de Bdeben definir foo(). Aquí es B,

class B 
{ 
public: 
     virtual int foo() = 0; //pure virtual function 
}; 

//pure virtual function also has a default implementation! 
int B::foo() 
{ 
     std::cout << "B" << std::endl; 
     this->foo(); //this will call the overridden foo() in the derived class! 
     return 0; 
} 

Si una clase derivada de B no implementa foo(), entonces ni siquiera se puede crear una instancia de esa clase derivada!

ver el código completo de trabajo en Ideone: http://www.ideone.com/m8O2s

Por cierto, mi opinión personal sería, como el diseño de las clases es malo para empezar. ¿Qué sucede si llama al B::foo() desde la clase derivada foo()? Recursivo?

+0

Esto lo hace para que no pueda instanciar una instancia de B. No sabemos si todavía quiere crear objetos de tipo B. –

+0

sí, por supuesto, me doy cuenta de que hay muchas maneras de ingeniar a su alrededor, pero mi La pregunta es si hay una forma integrada en C++ rtti para hacer lo que quiero. – deltamind106

0

Como han señalado otros, no hay una manera confiable de hacerlo. Le insto a que reconsidere su diseño ...

+0

bueno, sí, sería bueno si pudiera rediseñar el código incómodo del desarrollador anterior, pero lamentablemente eso no está en las tarjetas en este momento. – deltamind106

Cuestiones relacionadas