2012-02-09 20 views
5

Estoy intentando crear algunas clases de autoregistro en C++. Así que probé la solución similar a la proporcionada here. Mientras hago esto tropiezo con algo extraño.Inicialización de campo estático en la clase de plantilla en C++

Aquí está el código:

#include <iostream> 

class StaticClassType { 
public: 
    StaticClassType() { 
    // Notify when the static member is created 
    std::cout << "We're in." << std::endl; 
    } 
}; 


template<typename T> 
class TestClass1 { 
public: 
    TestClass1() { &m; } 
private: 
    // Static member in a template class 
    static StaticClassType m; 
}; 

template<typename T> 
StaticClassType TestClass1<T>::m; 


class TestClass2 : public TestClass1<TestClass2> { 
public: 
    TestClass2() { } // required; why? 
}; 


int main() { 
    return 0; 
} 

Este código crea la variable miembro estática TestClass1::m en el arranque (con ello la impresión "Estamos en." A la consola) - es decir, antes de iniciar main(). Sin embargo, el código solo funciona si escribo un constructor (vacío) para TestClass2 (como se muestra en el ejemplo).

¿Por qué tengo que escribir este constructor? ¿Por qué el constructor predeterminado generado por el compilador no hace lo mismo?

Este problema solo ocurre para las clases de plantilla. Si TestClass1 no era una clase de plantilla, el código funcionaría sin escribir el constructor vacío para TestClass2.

Respuesta

2

creé ejemplo aún más pequeño (sin constructores, que no son necesarios):

#include <iostream> 

class StaticClassType { 
public: 
    StaticClassType(int v) { 
    // Notify when the static member is created 
    std::cout << "We're in."<<v << std::endl; 
    } 
}; 


template<typename T> 
class TestClass1 { 
protected: 
    // Static member in a template class 
    static StaticClassType m; 
}; 

template<typename T> 
StaticClassType TestClass1<T>::m = StaticClassType(3); 


class TestClass2 : public TestClass1<TestClass2> { 
public: 
    void foo() 
    { 
     (void)m; 
    } 
}; 

int main() { 
    std::cout << "main" << std::endl; 
} 

tomar nota de que se necesita método foo(), de lo contrario el compilador elimina la variable estática, ya que no se utiliza en cualquier parte .

+0

según el nivel de optimización de su compilador, ya que foo no se usa en ninguna parte, no estoy seguro de que garantice que se creará una instancia. –

+0

@TomTanner Eso es correcto. El punto es que el compilador es libre de eliminarlo si no se usa en ningún lado. –

+0

Es por eso que tuve el constructor en TestClass1. Pero aún queda la pregunta: ¿por qué funciona cuando agrego un constructor vacío a TestClass2? ¿Cuál es la diferencia con el generado automáticamente por el compilador? –

0

Desde mi punto de vista, el "problema" es que en "mundo de plantillas" el compilador generará solo lo que realmente usa el código del cliente. Aquí Usted nunca instancia la clase TestClass2. Por lo tanto, no se generará una gran cantidad de código. Pruebe:

int main() { 

    TestClass2 instance; 
    return 0; 
} 

Y funciona en ese momento.

Cuestiones relacionadas