(C++) const_cast em função const, porque não funciona?

8 respostas
DavidUser
Tenho uma classe em C onde uma das suas funções deveria alterar os atributos mas ainda sim deve poder ser chamada por outras funções const da classe:
class MainTimeline {
	list<Post> newer;
	list<Post> industrious;
	list<Post> halted;

private:
	void reorganizeHalted() const;

public:
	MainTimeline();
	virtual ~MainTimeline();

	void includePost(const Post &post);
	const list<Post> &getNewerPosts() const;
	const list<Post> getNewerTypedPosts(string typeContent) const;
	const list<Post> &getHaltedPosts() const;
};

tive de tornar reorganizeHalted const para poder ser usada por outras funções const, mas parece que alterar os membros de dados usando const_cast não funciona com os membros de dados não criados dinâmicamente.

[size=18]Porque o const_cast não funciona corretamente com objetos que não foram criados dinamicamente?[/size]

8 Respostas

ViniGodoy

Você não pode “burlar” um const, nem mesmo com const_cast.
Tentar fazer isso é undefined behavior.

O compilador pode fazer cópia dos dados para garantir o constness, mesmo que o const cast seja usado:
http://www.pontov.com.br/site/cpp/46-conceitos-basicos/282-undefined-behavior

Tirar o const só serve para você chamar funções que não foram declaradas como const, que recebem um ponteiro ou referência para o objeto, mas não o alteram (geralmente, funções vindas do C ou erro de programação mesmo).

Por que as funções const estão tentando chamar um método que altera o próprio objeto? Nesse caso, elas não deveriam ser não const?

E

Membros que podem ser alterados por métodos const devem ser declarados como mutable.

mutable int contagem;
...
    void processa () const;
...
    void Classe::processa() const {
        contagem++;
E

http://www.highprogrammer.com/alan/rants/mutable.html

ViniGodoy

Entretanto, vale ressaltar que mutable é equivalente a dizer:
“Esse membro serve para fins internos do objeto e altera-lo não irá alterar o estado aparente do objeto”.

Ou seja, no exemplo do entanglement, o contador que é mutável é apenas um dado interno, que provavelmente será usado para fins de log/debug, algo que quem usa a classe não irá perceber que existe (e, portanto, para quem usa a classe, seu estado permanece visualmente imutável).

Isto é, não use mutable simplesmente como uma maneira de burlar o const.

Se você está precisando chamar um método não const, numa função const, pense com cuidado no seu design. As vezes a solução é simplesmente separar a operação mutável em outro método, por exemplo:

void updatePosts(); const list<Post> &getPosts() const; const list<Post> getTypedPosts(string typeContent) const; const list<Post> &getHaltedPosts() const;

DavidUser

Valeu pela explicação pessoal, realmente tive de mudar o design, não utilizo mutable pois isso tornaria os membros alteráveis por todas as funções const e o que buscava era como uma exceção para um método const em questão, logo vi que não tenho esse recurso, isso na verdade é um erro meu.

Muito Obrigado pela colaboração

J

entanglement:
Membros que podem ser alterados por métodos const devem ser declarados como mutable.

mutable int contagem; ... void processa () const; ... void Classe::processa() const { contagem++;

isso é uma coisa que me intriga. Normalmente eu usaria const somente para getters e para proteger referências passadas em parâmetros

DavidUser

juliocbq:
entanglement:
Membros que podem ser alterados por métodos const devem ser declarados como mutable.

mutable int contagem; ... void processa () const; ... void Classe::processa() const { contagem++;

isso é uma coisa que me intriga. Normalmente eu usaria const somente para getters e para proteger referências passadas em parâmetros

A utilização do const deve ser fortemente vinculada ao seu uso e isso inclui a parte conceitual, a questão é que que caso tenhamos uma instância constante de uma classe Busca, onde tal instância possa tem a funcionalidade realizar pesquisa (getter implícito) e disponibilizar os resultados, da mesma forma temos uma instância não const que tem funções que precisão alterar seu estado como mudar a fonte de busca dado que este era dado obrigatoriamente antes no construtor, poderiamos utilizar alguns membros de dados mutable para por exemplo contar como o exemplo acima, ou para especializar a busca de forma interna (oculto para o usuário).

const Search phonebookSeeker(myPhonebook);

   phonebookSeeker.quest("Alan");
   list<Contact> myJob = phonebookSeeker.resultByCategory("job");
   list<Contact> myFamily = phonebookSeeker.resultByCategory("family");
 ...
   //poderia repassar o buscador constante para outras funcoes que a necessitem para apenas fins de busca e que obrigatoriamente nao alteram a fonte
 ...
   //aqui a fonte ainda continua confiavel
Search allContactsSeeker(myPhonebook);

   allContactsSeeker.quest("Alan");
   list<Contact> myJob = allContactsSeeker.resultByCategory("job");
   list<Contact> myFamily = allContactsSeeker.resultByCategory("family");

   allContactsSeeker.setSource(myMailbox);
   allContactsSeeker.quest("Harper");
   list<Contact> famous = allContactsSeeker.allResults();
  ...
   //poderia repassar o buscador para outras funcoes que a necessitem para fins de busca e que alterem a fonte para chegar a melhores resultados
  ...
  //aqui a fonte so pode ser dita com uma leitura de suas utilizacoes previas incluindo chamadas de funcao que as utilizem, ainda sim podemos (devemos) reposicionar a fonte desejada

Tudo é uma questão de confiança para que utiliza as instâncias e funções.
Utilizei o exemplo pois não encontrei forma de me expressar melhor, caso alguém possa dar uma explicação mais sucinta seria interessante.

J

a explicação foi legal, obrigado.

Criado 8 de julho de 2012
Ultima resposta 9 de jul. de 2012
Respostas 8
Participantes 4