2011-05-16 18 views
7

Supongamos que tengo una clase en la que TC++ inicialización estática de la clase sin estado

  1. T no tiene funciones virtuales.
  2. T instancias no tienen estado.
  3. T tiene instancias de miembros estáticos de sí mismo.
  4. T no tiene otro estado.

¿Puede la inicialización estática de C++ fiasco arruinar mi programa? No lo creo, porque incluso si una de las instancias estáticas no se inicializa antes del uso, eso no debería importar porque los objetos T son apátridas.

Estoy interesado en hacer esto para las clases de enumeración similar, así:


// Switch.h 

class Switch { 
public: 
    static Switch const ON; 
    static Switch const OFF; 
    bool operator== (Switch const &s) const; 
    bool operator!= (Switch const &s) const; 
private: 
    Switch() {} 
    Switch (Switch const &); // no implementation 
    Switch & operator= (Switch const &); // no implementation 
}; 

// Switch.cpp 

Switch const Switch::ON; 
Switch const Switch::OFF; 

bool Switch::operator== (Switch const &s) const { 
    return this == &s; 
} 

bool Switch::operator!= (Switch const &s) const { 
    return this != &s; 
} 
+3

¡Excelente pregunta y una idea interesante! –

+0

¿Qué le da esto sobre una enumeración simple (sin el estado extra)? – Nim

+0

Por favor, publique un ejemplo de cómo realmente piensa utilizar la clase Switch. –

Respuesta

2

para responder a la primera parte de su pregunta , si T tiene un constructor que tiene efectos secundarios, entonces, de hecho, puede quemarse por la inicialización estática fiasco.

0

¿Realmente la intención de utilizar valores de puntero para comparar "estado"? Estoy de acuerdo con @Drew, es una idea interesante. Sin embargo, no estoy seguro de que esté garantizado por el estándar para funcionar, si suponemos que se trata de una implementación solo de encabezado.

Considere lo que sucede cuando varios objetos de compilación contienen la misma definición para Switch::ON y Switch::OFF. Como estas son variables, y no funciones, el vinculador tendría que decidir, arbitrariamente, entre ellas.

Cuando ejecutó una prueba, ¿qué dijeron los compiladores populares: gcc 3, gcc 4, microsoft C++ 2005, 2008 y 2010, y uno de los compiladores de Edison Design Groups como http://www.comeaucomputing.com/?

prueba

Said consistiría en:

// Switch.h 
class Switch { 
public: 
    static Switch const ON; 
    static Switch const OFF; 
    bool operator== (Switch const &s) const; 
    bool operator!= (Switch const &s) const; 
private: 
    Switch() {} 
    Switch (Switch const &); // no implementation 
    Switch & operator= (Switch const &); // no implementation 
}; 

Switch const Switch::ON; 
Switch const Switch::OFF; 

bool Switch::operator== (Switch const &s) const { 
    return this == &s; 
} 

bool Switch::operator!= (Switch const &s) const { 
    return this != &s; 
} 

y

// main.cpp 
#include "Switch.h" 

extern int another_test(); 

int main(int argc, char*argv[]) 
{ 
    another_test(); 
    const Switch& current_state = Switch::ON; 
    const Switch& another_state = Switch::OFF; 
    if (current_state == another_state) { 
    return 1; 
    } else if (current_state != another_state) { 
    return 2; 
    } 
    return another_test(); 
} 

y

// another_test.cpp 
#include "Switch.h" 

int another_test() 
{ 
    const Switch& current_state = Switch::ON; 
    const Switch& another_state = Switch::OFF; 
    if (current_state == another_state) { 
    return 4; 
    } else if (current_state != another_state) { 
    return 5; 
    } 
    return 6; 
} 
2

Estoy interesado en lo que son las ventajas que se ven desde, por ejemplo, una enumeración envuelto en un espacio de nombres o una clase:

namespace Switch { 
    enum Switch { 
     ON, 
     OFF 
    }; 
} 

Será más fácil de usar en la mayoría de los casos (en su implementación requiere que los usuarios empleen referencias o punteros, ya que los objetos no se pueden copiar), requiere menos código (no es necesario deshabilitar los constructores, crear los operadores) ...

Como cuestión de hecho, en el próximo estándar que casi consigue que de forma gratuita sin incluso el uso del espacio de nombres:

enum Switch { 
    ON, 
    OFF 
}; 
// bad, it allows this (as in the current standard): 
Switch s = ON; 
// good, it does also allow explicit qualification: 
Switch s = Switch::ON; 
+1

Nunca consideré esto. Aunque para ser un defensor del diablo, la variante de clase que propuse no permite la conversión implícita a ints. Además, no puedes reabrir una clase, pero eso se puede resolver envolviendo una clase en lugar de un espacio de nombres, supongo. –

Cuestiones relacionadas