Pergunta

Eu tenho um membro da classe MEMBER Aquilo é um meu tipo ponteiro. Quero atribuir este membro em uma função declarada como const. Estou fazendo o seguinte:

void func() const
{
     ...
     const_cast<myType*>(myMember) = new myType();
     ...
}

Isso funciona bem no VC ++, mas o GCC dá um erro com a mensagem "LValue necessária como operando esquerdo da atribuição".

Fazendo o membro mutável Permita -me simplesmente remover o const_cast e atribuir o valor. No entanto, não tenho certeza de que isso vem com outros efeitos colaterais.

Posso atribuir meu membro sem ter que tornar o membro mutável? Como? Existem efeitos colaterais em tornar os membros mutáveis?

Foi útil?

Solução

O código não funciona realmente no VC ++ - você não está atualizando o valor (ou pelo menos não deve), daí o aviso do GCC. O código correto é

const_cast<myType*&>(myMember) = new myType();

ou [de outra resposta, obrigado: P]:

const_cast<ThisType*>(this)->myMember = new myType();

Torná -lo mutável significa efetivamente que você fica implícito const_castpecado const Funções de membros, que geralmente é para isso que você deve estar dirigindo quando se vê fazendo muitos const_castfilho this. Não há 'efeitos colaterais para usar mutáveis' além disso.

Como você pode ver nos debates veementes que circulavam essa questão, o uso não mutable E muito const_castS definitivamente pode ser sintomas de maus cheiros em seu código. Do ponto de vista conceitual, eliminando a constência ou usando mutable pode ter implicações muito maiores. Em alguns casos, a coisa correta a fazer pode ser alterar o método para não-consagimento, ou seja, possuir o fato de estar modificando o estado.

Tudo depende de quanta correção de constituição é importante em seu contexto - você não quer acabar apenas aumentando mutable ao redor como pixie poeira para fazer as coisas funcionarem, mas mutable destina -se ao uso se o membro não for parte do estado observável do objeto. A visão mais rigorosa da correção da constituição sustentaria que nem um único pouco do estado do objeto pode ser modificado (por exemplo, isso pode ser crítico se você estiver na ROM ...) - nesses casos você não deseja nenhuma constência Estar perdido. Em outros casos, você pode ter algum estado externo armazenado em algum lugar do objeto - por exemplo, um cache específico para encadeamento que também precisa ser considerado ao decidir se é apropriado.

Outras dicas

Esse cenário - uma mudança de estado interno encapsulada que não afeta o estado externo (por exemplo, resultados de cache) - é exatamente o que o mutable palavra -chave é para.

const_cast é quase sempre um sinal de falha de design. No seu exemplo, também func() não deveria ser const, ou myMember deveria estar mutable.

Um chamador de func() esperará que seu objeto não mude; Mas isso significa "não mudar de uma maneira que ela possa notar"; Este é, para não mudar seu estado externo. Se mudar myMember não altera o estado externo do objeto, é isso que mutable palavra -chave é para; por outro lado, func() não deveria ser const, porque você estaria traindo sua função garante.

Lembre-se disso mutable não é um mecanismo para a correção da constituição circunevente; É um mecanismo para melhorá -lo.

class Class{
int value;
void func()const{
const_cast<Class*>(this)->value=123;
}
};

Como Steve Gilham escreveu, mutable é a resposta correta (e curta) à sua pergunta. Eu só quero dar uma dica em uma direção diferente. Talvez seja possível em seu szenario fazer uso de uma interface (ou mais de uma)? Talvez você possa se divertir no exemplo a seguir:

class IRestrictedWriter // may change only some members
{
public:
  virtual void func() = 0; 
}

class MyClass : virtual public IRestrictedWriter
{
public:
  virtual void func()
  {
    mValueToBeWrittenFromEverybody = 123; 
  }

  void otherFunctionNotAccessibleViaIRestrictedWriter()
  {
    mOtherValue1 = 123;
    mOtherValue2 = 345;
  }

  ...   
}

Então, se você passar para alguma função e IRestrictedReader * em vez de um const MyClass * pode ligar func e assim mude mValueToBeWrittenFromEverybody enquanto mOtherValue1 é meio "const".

. eu acho mutable Sempre um pouco de hack (mas use -o às vezes).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top