Проблемы с константой в C ++ при изменении значения члена с указателя на не указатель - PullRequest
0 голосов
/ 17 октября 2018

У меня есть два класса TestClass и OtherClass, где TestClass имеет переменную-член типа OtherClass с именем m_otherClass.Обратите внимание, что это не , объявленное как const.

В минимальном примере, представленном ниже;когда m_otherClass является указателем, тогда все компилируется и работает нормально.Если я изменяю это как не указатель, то я получаю ошибки компилятора (изменения закомментированы в минимальном примере):

"Неконстантная функция setOtherMember вызывается для объекта const"

ошибка: передача 'const OtherClass' в качестве аргумента 'this' отбрасывает квалификаторы [-fpermissive] m_otherClass.setOtherMember ();

#include <iostream>
#include <memory>

class OtherClass {
public:
    void setOtherMember() {
        m_otherMember = 2;
        std::cout << "Other member is now 2" << std::endl;
    }

private:
    int m_otherMember = 0;
};


class TestClass {
public:
    TestClass(): m_otherClass(std::make_unique<OtherClass>())
//  TestClass()
    {}

    void myMethod() const {
        m_otherClass->setOtherMember();
//      m_otherClass.setOtherMember();
    }
private:
        std::unique_ptr<OtherClass> m_otherClass;
//      OtherClass m_otherClass; // If changing to this I get the error!!
};


int main() {
    TestClass testClass;
    testClass.myMethod();
    return 0;
}

Isэто потому, что myMethod() является const (и затем обещает не изменять какие-либо переменные-члены), тогда как setOtherMember() не является const и изменяет переменную-член OtherClass, а затем косвенно также объект m_otherClass?

Но почему это не дает сбоя тогда, когда m_otherClass является указателем?И почему ошибка компилятора говорит о том, что передача const OtherClass в качестве аргумента this завершается ошибкой, когда m_otherClass не был объявлен как const?

Ответы [ 4 ]

0 голосов
/ 17 октября 2018

Квалифицированным функциям-членам Const в большинстве случаев не разрешается изменять состояние членов объекта.Это означает, что каждый элемент, который не является изменяемым, не может быть изменен в этом теле функции.Имея дело с указателями, вы просто говорите, что не будете изменять значение указателя, а не самого указателя.Это связано с тем, что константа указателя не распространяется на его указатель .

В следующих стандартах можно будет изменить это поведение с помощью пропагата_конст .

0 голосов
/ 17 октября 2018

Более простой пример, демонстрирующий разницу.

struct Foo { int m; };

const Foo f = {10}; 
f.m = 20; // Not allowed since modifying f.m modifies f.

struct Bar { int* p; };
int i = 10;
int j = 20;

const Bar b = {&i};

b.p = &j;    // Not allowed since modifying b.p modifies b.

*(b.p) = j;  // Allowed since it does not change b or b.p. It changes the value
             // of what b.p points to.
0 голосов
/ 17 октября 2018

Когда вы добавляете const к методу, все ваши элементы данных обрабатываются как const.И именно поэтому вы получаете ошибку, когда у вас есть OtherClass в качестве значения, так как оно превращается в значение const OtherClass.

Теперь, когда вы используете указатель OtherClass, вы получаете const std::unique_ptr<OtherClass> иconst применяется только к указателю, но не к значению, на которое он указывает.

0 голосов
/ 17 октября 2018

Но почему это не дает сбоя тогда, когда m_otherClass является указателем?

Поскольку корректно модифицировать объект, на который указывает указатель const, до тех пор, пока онуказатель на неконстантный, такой как в вашем случае.

И почему ошибка компилятора говорит, что передача 'const OtherClass' как 'this' аргумент завершается неудачно, когда m_otherClass не был объявлен как const?

myMethod объявлен постоянным.Следовательно, this является указателем на const.Поэтому lvalue this->m_otherClass также является const независимо от того, является ли объект, названный lvalue, постоянным или нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...