Почему константа не применяется для указателей?
Рассмотрим следующий фрагмент кода:
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()
независимо от типа объекта A.
Однако компилятор жалуется на объект, но не на указатель. Зачем? Я использую VS2017 в Windows 10.
Ответы
Ответ 1
Он применяется.
Если вы попытаетесь изменить указатель, компилятор не позволит вам.
Тем не менее, указывает указатель на другой разговор.
Помните, что T* const
и T const*
- это не одно и то же!
Вы можете защитить это, либо сделав его A const*
, либо просто написав свою функцию таким образом, который подходит.
Ответ 2
Другие ответы объясняют T* const
vs T const *
что и происходит. Но важно понимать, что это означает не только простой синтаксис.
Когда у вас есть T*
внутри структуры, указатель находится внутри объекта, но указанный объект физически находится за пределами структуры. Поэтому для объекта const с членом T*
не разрешается изменять указатель, но ему разрешено изменять заостренный объект, потому что физически заостренный объект находится за пределами объекта-объекта.
И программист должен решить, является ли заостренный объект логически частью объекта-объекта (и, как таковой, должен разделять константу с приложением), или если он логически является внешним объектом.
Недостаток C++ заключается в том, что он не предлагает простой способ выразить логическую константу, как указано выше (что вы действительно ожидали от своего кода).
Это известно и для этой точной цели есть экспериментальный класс, который еще не является стандартом propagate_const
std :: experimental :: propagate_const - это const-распространяющая оболочка для указателей и указательных объектов. Он обрабатывает завернутый указатель как указатель на const при доступе через путь доступа к const, отсюда и название.
struct B
{
A a_;
std::experimental::propagate_const<A *> pA_;
void fun()
{
pA_->nonConstFun(); // OK
}
void fun() const
{
// pA_->nonConstFun(); // compilation error
}
};