为什么没有强制指针的const?

Aru*_*run 23 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();
}
Run Code Online (Sandbox Code Playgroud)

在这里,我期望编译器在编译时因为缺少常量来调用A::nonConstFun()内部,B::fun()而不管A对象的类型如何.

但是编译器会抱怨该对象,而不是指针.为什么?我在Windows 10上使用VS2017.

bol*_*lov 52

其他答案解释了T* constvs T const *正在发生的事情.但重要的是要理解这不仅仅是单纯的语法.

当你有一个T*结构内部时,指针在对象内部,但指向的对象在物理上位于结构之外.这就是为什么对于带有T*成员的const对象,不允许修改指针,但允许修改指向对象 - 因为物理上指向的对象在封闭对象之外.

并且由程序员决定指向的对象是否在逻辑上是封闭对象的一部分(因此应该与封闭对象共享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
    }
};
Run Code Online (Sandbox Code Playgroud)


Lig*_*ica 43

强制执行的.

如果您尝试更改指针,编译器将不会让您.

然而,指针所指向的是一个不同的对话.

请记住,T* const并且T const*是不一样的东西!

您可以通过实际制作它A const*,或者仅仅通过以适当的方式编写您的功能来保护它.

  • 我经常发现像[cdecl.org](http://cdecl.org)这样的工具对于确保我以与编译器读取它相同的方式读取`const`非常有用. (2认同)