Tengo un pequeño problema con la anulación de los métodos estáticos de las clases base, pero toda la pregunta es muy complicada y demasiado larga (generalización de la gestión de recursos en el motor del juego), así que aquí hay una versión simplificada:
template<class T>
class base
{
static void bar()
{ printf("bar"); }
public:
static void foo()
{ bar(); }
};
class derived : public base<int>
{
static void bar()
{ printf("baz"); }
};
int main() { derived::foo(); }
El código anterior genera “barra” en mi caso, en lugar de eso, quiero que genere “baz”. ¿Cómo puedo hacer eso? Parece que no importa lo que intente, base::foo() siempre llama a base::bar(). Podría tener un problema con el diseño. Nunca me he encontrado con este problema, ¿cómo puedo resolverlo?
YSC
Lo que está tratando de hacer no se puede lograr con la herencia de clase simple; un método no puede ser ambos static
y virtual
.
Tu necesitas un static
método para poder llamar a una función sin un objeto (una instancia); y tu necesitas bar
ser – estar virtual
de modo que bar<int>::foo()
llamadas derived::bar()
cuando se llama desde un derived
instancia.
Esos dos rasgos son mutuamente excluyentes. Pero el Patrón de plantilla curiosamente recursivo (CRTP) puede ser una solución aquí:
#include <iostream>
template<class T>
struct base
{
static void foo()
{
T::bar();
}
};
struct derived : public base<derived>
{
static void bar()
{
std::cout << "derived" << std::endl;
}
};
int main()
{
derived::foo();
}
-
¡Muchos gracias! me ayudo tu respuesta!
– ryo
2 de febrero de 2017 a las 12:06
-
Esta respuesta me voló la cabeza. ¿Cómo sabe el compilador que habrá una barra de método () en la clase T? ¿Comprueba estáticamente cada instancia de base
para asegurarse de que se ajuste al uso? – mayacoda
27 de marzo de 2018 a las 15:05
-
@MayaNedeljkovich No es así. Cada vez que una especialización de
base<T>::foo
se hace (en el programa de ejemplo, la hora exactabase<derived>::foo
se llama), se lo hace Mira estobase<T>::foo
dar sentido a lo dadoT
. Esta es la llamada compilación de segundo paso de plantilla (también conocida como “en contexto deducido”). Si no fuera el caso, => error de compilación. Pruébelo usted mismo.– YSC
27 de marzo de 2018 a las 15:08
-
@YSC: ¡+1 por proporcionar ejemplos en vivo dos veces!
– Trapicki
11 de julio de 2020 a las 13:30
-
@MayaNedeljkovich Por lo general, en rust podemos usar el rasgo vinculado a los argumentos de la plantilla. En cpp20, parece que hay un concepto similar llamado “concepto”, no soy un maestro de la plantilla de C++, pero creo que
stdlib podría ayudar antes de cpp20. – Jurado
13 de octubre a las 1:56
No puede anular los métodos estáticos. Puede sobrecargarlos (que es lo que está haciendo aquí), pero solo está recibiendo un despacho estático. Supongo que podrías usar el CRTP.
– TartánLlama
11 de diciembre de 2015 a las 11:41
Posible duplicado de métodos virtuales estáticos alternativos a c ++
– jww
11 de junio de 2017 a las 16:08