为什么 const 正确性规则不适用于内置库?

Why const correctness rule doesn't work for built in libraries?

const 方法有一条规则。如果方法是 const,而我们试图在同一个方法中使用另一个函数,那么它也应该是 const。否则,我们将出现编译错误。我试图在 math.h 库中找到 abs() 函数的声明,这是我找到的:Declarations of abs() 这意味着 abs() 函数不是 const,但是当我在 const 方法中使用它时,我没有出现编译错误。有人可以解释这是为什么吗?

class D:public B,C
{
public:
    D()
    {
        cout<<"This is constuctor D"<<endl;
    }

    int fun3() const;

    ~D()
    {
         cout<< "Destructor D"<<endl;
    }
};

int D::fun3() const
{
    int x=-3;

    return abs(x);
}

这里对const成员函数的约束有误解

一个const成员函数可以调用它想要的任何函数,只要它不改变对象的状态。所以 fun3() 编译得非常好,因为它不会更改任何成员变量,也不会为同一对象调用任何非常量成员函数。

重要说明: public B,C可能不是你想的那样:这意味着D公开继承自B,私有来自 C。如果您希望它从 C 公开继承,则必须声明 public B, public C

const 应用于方法仅意味着 this 指针,即指向该方法正在运行的实例的指针,是 const。这意味着它不能修改字段,只能调用 const 方法 在它上面 ,一般情况下不会。

调用自由函数是完全可以接受的,甚至可以在同一 class 的 不同对象 上调用非 const 方法,只要因为这样的对象不是 const

首先,忘记你认为你知道的东西。让我们看看成为 const 会员意味着什么。

class D {
public:
    int fun2();
    int fun3() const;
};

这说明了什么?有个叫D的class。有两个成员函数 fun2fun3,每个函数都有一个隐藏的 this 参数,没有其他参数。

坚持住!隐藏参数?嗯,是。您可以在函数内使用 this;它的价值必须来自某个地方。所有非静态成员函数都有这个隐藏参数。但是,并非所有非静态成员函数都具有相同类型的隐藏参数。如果我要显示隐藏参数,声明将如下所示:

int D::fun2(D * this);
int D::fun3(const D * this);

请注意 const 是如何存在于这个伪声明中的?这就是声明一个 const 成员函数的效果:this 指向一个 const 对象而不是一个非 const 对象。

现在回到问题。 fun3 可以调用 fun2 吗?那么,fun3 会将它的 this 指针(一个指向常量对象的指针)传递给 fun2,它需要一个指向对象的指针。那将意味着失去常量,所以这是不允许的。

可以fun3调用abs吗?那么,fun3 会将一个整数传递给 abs。这里没问题。问题是失去了 this 的常量性。只要避免这种情况,就可以了。

考虑一下

#include <iostream>

int f(int num) { return num+1; }
int fr(int& num) { return num+1; }
int fcr(const int& num) { return num+1; }

class D
{
public:
    int value= 0;

public:
    void f1() { value++; }
    int f2() const { return value; }
    int f3() { return value; }
    static void f4() { std::cout << "Hello" << std::endl; }
    void f5() const;
};

void D::f5() const
{
    // Prohibited:
    // f1(); // modifies this
    // f3(); // might modify this
    // value++; // modifies this->value, thus modifies this
    // value= 2; // modifies this->value, thus modifies this
    // value= abs(value); // modifies this->value, thus modifies this
    // fr(value); // takes value by reference and might modify it
    // 
    // Permitted:
    f2(); // const function, does not modify this
    std::cout << value << std::endl; // independent function, does not modify this; read access to this->value is const
    std::cout << abs(value) << std::endl; // independent function, does not modify this; read access to this->value is const
    f4(); // static function, does not modify this
    f(value); // function, does not modify this; takes value as read only (makes copy)
    fcr(value); // function, does not modify this; takes value as read only by reference

    D otherObject;
    otherObject.f1(); // modifies otherObject (non const), does not modify this
}

int main()
{
    const D d;
    d.f5();
}

每当你在 f5() 中调用像 f4() 这样的成员函数时,你传递的是一个隐式的 this 指针,相当于 this->f4()。在 f5() 中,因为它是 const,所以它不是 D* 类型,而是 const D* 类型。所以你不能做 value++(相当于 this->value++ 对于 const D*。但是你可以调用 absprintf 或任何不需要 this 并尝试修改它)。

当你取this->value时,如果this类型是D*,它的类型是int,你可以自由修改它。如果你对 const D* 做同样的事情,它的类型变成 const int,你不能修改它,但可以复制它并作为常量引用访问它以供读取。