Modificando-se dentro do método const por meio de um ponteiro não const para si mesmo

StackOverflow https://stackoverflow.com//questions/22053806

  •  21-12-2019
  •  | 
  •  

Pergunta

No exemplo a seguir const objeto pode se modificar através const método, porque nesse método ele se acessa via non-const ponteiro.(mesmo programa no ideone)

#include <iostream>

struct Object;

Object * g_pObject;

struct Object
{
    Object():m_a(0){}

    void ModifySelfViaConstMethod() const
    {
        g_pObject->m_a = 37;
    }

    int m_a;
};

int main()
{
    Object o;
    g_pObject = &o;

    const Object & co = o;
    std::cout << co.m_a << "\n";
    co.ModifySelfViaConstMethod();
    std::cout << co.m_a << "\n";

    return 0;
}

Não sou muito bom em ler o padrão c++, então pergunto aqui:

O que a norma diz sobre isso?

a)const método não garante que seu objeto permaneça inalterado quando você faz coisas assim

b) Está bem definido e deve compilar

c) outro?

Foi útil?

Solução

O que a norma diz sobre isso?

Diz (parafraseando) que this tem tipo const Object *, para que você não possa modificar membros diretamente ou chamar funções de membro não const por meio de this.Não diz nada sobre o que você pode fazer com quaisquer variáveis ​​globais às quais a função possa ter acesso;ele controla apenas o acesso direto ao objeto no qual a função é chamada.

const método não garante que seu objeto permaneça inalterado quando você faz coisas assim

Não, não importa.Ele afirma a intenção de que a função não modifique o objeto e fornece alguma proteção contra a quebra acidental dessa intenção.Isso não impede que um programador adequadamente perturbado use const_cast, ou (como aqui) acoplamento descontrolado por meio de variáveis ​​globais para quebrar a promessa.

Está bem definido isso e deve compilar

Sim. o não é constante, portanto não há nada que impeça você de usar um ponteiro não const ou fazer referência a ele.O const na função membro restringe apenas o acesso ao objeto via this, não para objetos arbitrários por meio de outros ponteiros.

Outras dicas

Quando você declara um const função, é "para o seu próprio bem".

Em outras palavras, você declara const porque de acordo com seu design inicial, não é suposto alterar nenhum objeto com o qual será invocado durante o tempo de execução.

Se durante algum momento posterior da implementação desta função você acabar alterando o objeto, o compilador irá "gritar com você", dizendo que está errado.

É claro que o compilador será capaz de identificar tal tentativa, somente quando aplicada em this.

No exemplo dado, o compilador não consegue identificar o problema porque requer uma comparação entre this e g_pObject, e essa comparação só pode ocorrer durante o tempo de execução.

Quando um método é declarado como const, o compilador garante que a instância apontada pelo this ponteiro não é modificado.Se você tentar modificar o this por exemplo, o compilador falhará.No entanto, o compilador não tem como saber que g_pObject e this estão realmente apontando para a mesma instância.Isso requer uma comparação em tempo de execução, e nenhum compilador perderá tempo realizando comparações em tempo de execução de cada ponteiro usado dentro de um const método na eventualidade de que eles poder combinar com o this ponteiro.Então, se você for modificar um Object através de um ponteiro externo, você terá que fazer sua própria verificação, por exemplo:

void ModifySelfViaConstMethod() const
{
    if (g_pObject != this)
        g_pObject->m_a = 37;
}

A constância em C++ é um instrumento de segurança, não de segurança.

O código onde a constância é respeitada provavelmente funcionará conforme o esperado, e todas as tentativas não intencionais de eliminar a constância serão alertadas pelo compilador.

Nos casos em que "sei o que estou fazendo" pode-se encontrar toda a variedade de ferramentas, desde const_cast operador e mutable palavra-chave para o elenco banal do estilo C.

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