Изменение self внутри метода const с помощью неконстантного указателя на себя

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

  •  21-12-2019
  •  | 
  •  

Вопрос

В следующем примере const объект может изменять себя через const метод, потому что в этом методе он обращается к самому себе через non-const указатель.(та же программа на 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;
}

Я не очень хорошо разбираюсь в стандартах C++, поэтому спрашиваю здесь:

Что по этому поводу говорит стандарт?

а)const метод не гарантирует вам, что ваш объект останется неизменным, когда вы делаете такие вещи

б) Это четко определено и должно быть скомпилировано

в) другое?

Это было полезно?

Решение

Что стандарт говорит об этом?

Он говорит (перефразирование), что this имеет тип const Object *, так что вы не можете напрямую изменять элементы или вызовать функции членов Non-Const через this. Это ничего не говорит о том, что вы можете сделать с любыми глобальными переменными, к которым функция может иметь доступ к; Он только контролирует прямой доступ к объекту, на которой вызывается функция.

Способ const не гарантирует вас, что ваш объект остается неизмененным, когда вы делаете такие вещи

Нет, это не так. Он заявляет о намерении, что функция не модифицирует объект, и обеспечивает некоторую защиту от случайного нарушения этого намерения. Он не предотвращает использование подходящего небуманного программиста с использованием const_cast или (как здесь) неконтролируемая связь через глобальные переменные, чтобы нарушить обещание.

Это четко определено, что и он должен компилировать

Да. o не сам по себе постоянна, поэтому нет ничего, чтобы остановить, что вы принимаете указатель или ссылку на нее. Генеракодицетагкод на функцию элементов ограничивает доступ к объекту через const, а не произвольными объектами по другим указателям.

Другие советы

Когда вы объявляете const функция, это "для вашего же блага".

Другими словами, вы заявляете об этом const потому что, согласно вашему первоначальному дизайну, не предполагается изменять какой-либо объект, с помощью которого он будет вызван во время выполнения.

Если на каком-то более позднем этапе реализации этой функции вы в конечном итоге измените объект, компилятор "накричит на вас", сообщив, что это неправильно.

Конечно, компилятор сможет идентифицировать такую попытку только при применении к this.

В приведенном примере компилятор не может идентифицировать проблему, поскольку для этого требуется сравнение между this и g_pObject, и такое сравнение может иметь место только во время выполнения.

Когда метод объявлен как const, компилятор гарантирует, что экземпляр, на который указывает this указатель не изменяется.Если вы попытаетесь изменить this например, компилятор потерпит неудачу.Однако компилятор не имеет возможности узнать об этом. g_pObject и this на самом деле указывают на один и тот же экземпляр.Для этого требуется сравнение во время выполнения, и ни один компилятор не будет тратить время на сравнение во время выполнения каждого указателя, используемого внутри const метод на тот случай, если они мощь соответствовать this указатель.Итак, если вы собираетесь изменить Object через внешний указатель вам придется выполнить собственную проверку, например:

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

Постоянство в C ++ - это инструмент безопасности, а не защита.

Код, в котором соблюдается постоянство, скорее всего, будет работать так, как ожидалось, и все непреднамеренные попытки отбросить постоянство будут предупреждены компилятором.

В случаях, когда "Я знаю, что я делаю", можно найти все разнообразие инструментов, начиная с const_cast оператор и mutable ключевое слово для приведения в банальном стиле C.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top