上一篇介绍了const修饰的变量或者指针的含义,这篇我们介绍const修饰的函数以及函数参数含义。
首先我们看一个例子
class Dog{int age;string name; public:Dog(){age = 3;name = "dummy";}void setAge(const int &a){age = a;a++;} };int main(){Dog d;int i = 9;d.setAge(i);cout << i << endl; }
在上面例子中,如果setAge中参数不加上const,则可能通过该函数修改i的值,如果这不是我们想要的,那么就可以通过对参数使用const。编译的时候会报错。
const在C++中是非常常用的一个修饰,我们在合适的时候就要尽量用上这样的修饰符,可以增加代码的健壮性和可读性。
下面我们再看一个例子,如果我们将function参数上面的引用符去掉的话,又会有什么变化呢?
class Dog{int age;string name; public:Dog(){age = 3;name = "dummy";}void setAge(const int a){age = a;
// compile error// a++;}
void setAge(int a){age = a;
// compile error// a++;}
};int main(){Dog d;int i = 9;d.setAge(i);cout << i << endl; }
这样,自然编译成功,这里需要学习的是如果将引用去掉,那么就是值传递,i做了一个值拷贝给了这个函数,自己不会发生变化,这个C++初学者也是明白的道理。
如果我们将上面setAge函数的参数的const去掉,作为函数重载,那么编译也会错误,因为C++在重载的时候必须要有不同的参数表,而const int和int会被编译器认为是同种类型。
返回值为const的函数:
class Dog{int age;string name;public:Dog(){age = 3; name = "dummy";}// const parametersvoid setAge(const int& a) {age = a; cout<<"const"<<endl;}void setAge(int& a) {age = a; cout<<"non-const"<<endl;}// const return value_compconst string& getName(){return name;}// const functionavoid printDogName() const {cout << "const" << endl;}void printDogName() {cout << "non-const" << endl;} };int main(){Dog d;const string& n = d.getName();cout << n << endl;
d.printDogName();
Dog d2;
d2.printDogName();
}
output: dummy const non-const
上面例子非常清楚地展示了const修饰的function的作用效果,const如果在function后面,表示该function会在该对象为const时调用。需要注意的是,如果类的成员函数修饰为const,那么该函数中只能调用const函数,也就是说,上面的const函数不能调用getName,因为getName函数不是const函数。
如果把上面printDogName的const去除,是不是表示该函数被重载了呢?答案是肯定的,那么问题来了 ,什么时候const修饰的函数被调用,又什么时候没有const修饰的函数被调用呢?大家可以写一写,弄清楚,这里就直接公布答案了:
当Dog为const时,const函数会被优先执行,当Dog不是const时,会优先执行非const函数(当然,前提是这两个函数都要有,如果没有函数重载,那么就会调用唯一的那个函数,不会报错)。
刚才说了const修饰的函数的调用规则,那么function参数是否有const的调用规则如何呢?规则如下:如果传入的参数为const修饰的,那么将会调用函数参数中有const修饰的那个。其实这个简单的规则还可以细说,将会以Lvalue和Rvalue在后续的博文中继续说明。