Рассмотрим следующий фрагмент кода:
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.
Это является исполнение.
Если вы попытаетесь изменить указатель, компилятор не позволит вам.
Однако на что указывает указатель, это другой разговор.
Помните, T* const
а также T const*
это не одно и то же!
Вы можете защитить это, либо сделав это A const*
или просто написав свою функцию соответствующим образом.
Другие ответы объясняют 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
}
};