为什么不对指针强制使用constness?

时间:2018-10-02 11:39:52

标签: c++ pointers const transitive-const

请考虑以下代码段:

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。

2 个答案:

答案 0 :(得分:51)

其他答案解释了T* constT 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*来保护它,也可以通过以适当的方式编写函数来保护它。