请考虑以下代码段:
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对象的类型无关。
但是,编译器抱怨的是对象,而不是指针。为什么? 我正在Windows 10上使用VS2017。
答案 0 :(得分:51)
其他答案解释了T* const
与T const *
的变化。但是,重要的是要了解仅含语法之外的含义。
当在结构内部有T*
时,指针位于对象内部,但指向的对象实际上位于结构外部。这就是为什么对于具有T*
成员的const对象,不允许修改指针,但可以修改指向的对象的原因-因为实际上指向的对象在包围对象的外部。
由程序员决定指向的对象是否在逻辑上是封闭对象的一部分(因此应该与封闭对象共享常量),或者从逻辑上讲,它是外部实体。
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
}
};
答案 1 :(得分:43)
强制执行 。
如果您尝试更改指针,编译器将不允许您使用。
但是,指针所指向的是另一种对话。
请记住,a[0]
和T* const
不是同一个人!
您可以通过实际制作T const*
来保护它,也可以通过以适当的方式编写函数来保护它。