Pergunta

Suponha que eu tenha uma classe T onde

  1. T não tem funções virtuais.
  2. T casos não têm estado.
  3. T tem de membro estático instâncias de si mesmo.
  4. T em si não tem nenhum outro estado.

Pode o C++ inicialização estática fiasco arruinar o meu programa?Eu não penso assim, porque mesmo se um dos estáticos instâncias não é inicializado antes do uso, que deve não importa, porque T objetos são apátridas.

Eu estou interessado em fazer isso por enum-como classes, como por exemplo:


// 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;
}
Foi útil?

Solução

Para responder à primeira parte da sua pergunta, se T tem um construtor que tem efeitos colaterais, em seguida, você pode, de fato, ter queimado pela inicialização estática fiasco.

Outras dicas

Eu estou interessado em quais são as vantagens que você vê, por exemplo, um enum envolto em um namespace ou de uma classe:

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

Ele vai ser mais simples de usar na maioria dos casos (na sua implementação que exigem que os usuários utilizam referências ou ponteiros, como os objetos não são copiáveis), requer menos código (não há necessidade de desativar os construtores, e criar para os operadores)...

Como uma questão de fato, nos próximos padrão é quase conseguir isso de graça, mesmo sem a utilização do espaço de nomes:

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;

Você realmente pretende usar valores de ponteiro para comparar "estado"?Eu concordo com o @Drew, que é uma ideia interessante.Não tenho certeza se é garantida pelo padrão de trabalho, no entanto, se partirmos do princípio de que este é um cabeçalho só de implementação.

Considere o que acontece quando vários compilação objetos contêm a mesma definição para Switch::ON e Switch::OFF.Uma vez que estas são variáveis, e não as funções, o vinculador teria de decidir, de forma arbitrária, entre eles.

Quando você executou um teste, o que fez o popular compiladores dizer:gcc 3, o gcc 4, microsoft C++ 2005, 2008 e 2010, e um dos Edison Design dos Grupos de compiladores, como http://www.comeaucomputing.com/ ?

Disse o teste consistirá de:

// 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;
}

e

// 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();
}

e

// 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;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top