何为常量函数

1.this指针

当我们调用成员函数时,实际上是在替某个对象调用它。成员函数通过一个名为this指针的隐式参数来访问它调用的对象的地址,这样在成员函数内部,我们就可以使用this来访问类内成员。那么由于this始终指向这个地址,所以它是一个常量指针,不允许改变它所保存的对象地址。但是this对应的是指向类类型的非常量版本的常量指针,我们知道,这样的指针是不能绑定到一个常量对象上的。具体看下面的例子:

class people{
    public:
        people(){}
        people(int x):score(x){}
        ~people(){}
        int getScore(){return score;}
    private:
        int score;
};

int main(){
    const people p1(22);//常量
    cout << p1.getScore() << endl; //error,不能用常量绑定非常量指针
    return 0;
}

这段代码在编译器中是无法编译通过的。我们知道用指向常量的指针来绑定常量和非常量都是可以的,那么为了提高成员函数的灵活性,我们就可以将这个this指针定义为指向常量的指针(同时其本身就是常量指针)。方法就是在成员函数的参数列表后面加入关键字const,则上述getScore函数修改为:

int getScore() const {return score;}

这样上述代码的main函数就可以正常运行了。

2.补充

对于成员函数,其有一个隐式参数,来表示对象的地址,例如:

class Foo{
    public:
        void hello(int a){
            cout << "hello" + a << endl;
        }
        //等价于
        //void hello(Foo* const this, int a){
            //out << "hello" + a << endl;
        //}
};

int main(){
    Foo foo;
    int a = 2;
    foo.hello(a);
    //等价于
    foo.hello(&foo, a);
}

上面的代码展示了对象地址的隐式参数传递,当我们将hello设置为常量函数后,就可以理解为其等价版本变为:

void hello(const Foo* const this, int a){
    out << "hello" + a << endl;
}

3.常量成员函数的重载

两个成员函数,名字和参数列表都一样,但是一个是常量函数一个不是,则也算重载。

class people{
    public:
        people(){}
        people(int x):score(x){}
        ~people(){}
        int getScore() {return score;}
        int getScore() const {return score};
    private:
        int score;
};

int main(){
    const people p1(22);//常量对象
    people p2(23); //非常量对象
    cout << p1.getScore() << p2.getScore() << endl; //重载
    return 0;
}