Почему константность не применяется для указателей?

Рассмотрим следующий фрагмент кода:

class A
{
public:

void nonConstFun()
{

}
};

class B
{
private:

A a_;
A * pA_;

public:

void fun() const
{
pA_->nonConstFun();
//a_.nonConstFun(); // Gives const related error
}
};

int main()
{
B b;
b.fun();
}

Здесь я ожидаю, что компилятор не сможет выполнить компиляцию из-за отсутствия константности для вызова A::nonConstFun() внутри B::fun() независимо от типа объекта.

Однако компилятор жалуется на объект, но не на указатель. Зачем?
Я использую VS2017 на Windows 10.

23

Решение

Это является исполнение.

Если вы попытаетесь изменить указатель, компилятор не позволит вам.

Однако на что указывает указатель, это другой разговор.

Помните, T* const а также T const* это не одно и то же!

Вы можете защитить это, либо сделав это A const*или просто написав свою функцию соответствующим образом.

43

Другие решения

Другие ответы объясняют T* const против T const * что и происходит. Но важно понять значение этого за пределами простого синтаксиса.

Когда у вас есть T* внутри структуры указатель находится внутри объекта, но указанный объект физически находится вне структуры. Вот почему для const объекта с T* Члену запрещено изменять указатель, но можно изменять указанный объект — потому что физически указанный объект находится за пределами охватывающего объекта.

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

Недостаток C ++ состоит в том, что он не предлагает простой способ выразить логическую константу, как указано выше (что вы на самом деле ожидали от своего кода).

Это известно, и для этой цели существует экспериментальный класс, который еще не является стандартным propagate_const

std :: экспериментальный :: пропагат_конст — это распространяющая константу оболочка для
указатели и объекты, похожие на указатели. Обрабатывает завернутый указатель как
указатель на const при доступе через путь доступа к const, следовательно,
название.

struct B
{
A a_;
std::experimental::propagate_const<A *> pA_;

void fun()
{
pA_->nonConstFun(); // OK
}
void fun() const
{
// pA_->nonConstFun(); // compilation error
}
};
51

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector