const member functions (常量成员函数)
告诉编译器,该成员函数不能改变类的成员变量
项目 | const object(常量对象 data members不能改变) | non-const object(非常量对象 data members可以改变) |
---|---|---|
const member functions(保证不更改data members) | yes | yes |
non-const member functions(不保证data members不变) | no | yes |
当成员函数的const和non-const版本同时存在,const object只能调用const版本,non-const object只能调用non-const版本;
class template std::basic_string<…> 有如下两个member functions:
charT operator[](size_type pos) const { /不必考虑 Copy on Write / }
reference operator[](size_type pos) { /必须考虑 Copy on Write / }
string 采用的是计数模式,所以一个相同内容相同的变量会共享。上面的两个函数,可能被拿来修改数据,所以里面需要做Copy on Write,即:假如str1,str2,str3的内容都是”aaaaa”,那么他们三个会共享”aaaaaa”,但是其中某个字符串要修改内容,str1要修改字符串中的第二个字符为’b’,则会先复制一份”aaaaaa”,然后修改成”abaaaa”。这时候str2和str3还是会共享”aaaaaa”,但是str1则不会,其值为”abaaaa”。
看下面一个例子:
代码1
class Test {
public:
void fun(int i) { cout << "i: " << i << " fun non-const" << endl; }
//void fun(int i) const { cout << "i: " << i << " fun const" << endl; }
};
int main(int argc, char *argv[]) {
Test test;
test.fun(1);
return 0;
}
输出结果:
fun non-const
代码2
class Test {
public:
//void fun(int i) { cout << "i: " << i << " fun non-const" << endl; }
void fun(int i) const { cout << "i: " << i << " fun const" << endl; }
};
int main(int argc, char *argv[]) {
Test test;
test.fun(1);
return 0;
}
输出结果:
i: 1 fun const
上面两个代码测试,可以看出,非const的对象既可以调用常量成员函数,也可以调用非常量成员函数。那如果这两个函数同时存在,会构成重载嘛?如果构成重载,非const的对象会调用那一个呢?看下面代码…
代码3
class Test {
public:
void fun(int i) { cout << "i: " << i << " fun non-const" << endl; }
void fun(int i) const { cout << "i: " << i << " fun const" << endl; }
};
int main(int argc, char *argv[]) {
Test test;
test.fun(1);
return 0;
}
输出结果:
i: 1 fun non-const
代码3顺利编译通过,并运行输出i: 1 fun non-const
,说明:在常量成员函数和非常量成员函数同时存在的时候,非常量对象会调用非常量成员函数。
代码4
class Test {
public:
void fun(int i) { cout << "i: " << i << " fun non-const" << endl; }
//void fun(int i) const { cout << "i: " << i << " fun const" << endl; }
};
int main(int argc, char *argv[]) {
const Test constTest;
constTest.fun(2);
return 0;
}
编译出错:
error: member function 'fun' not viable: 'this' argument has type 'const Test', but function is not marked const
constTest.fun(2);
常量对象调用非常量成员函数,编译不通过。
代码5
class Test {
public:
//void fun(int i) { cout << "i: " << i << " fun non-const" << endl; }
void fun(int i) const { cout << "i: " << i << " fun const" << endl; }
};
int main(int argc, char *argv[]) {
const Test constTest;
constTest.fun(2);
return 0;
}
输出结果:
i: 2 fun const
常量对象调用常量成员函数,没有问题。 但是如果:常量成员函数和非常量成员函数都存在的时候,常量对象会调用那个呢?
代码6
class Test {
public:
void fun(int i) { cout << "i: " << i << " fun non-const" << endl; }
void fun(int i) const { cout << "i: " << i << " fun const" << endl; }
};
int main(int argc, char *argv[]) {
const Test constTest;
constTest.fun(2);
return 0;
}
输出结果:
i: 2 fun const
常量成员函数和非常量成员函数都存在的时候,常量对象将调用常量成员函数。
代码7
class Test {
public:
void fun(int i) { cout << "i: " << i << " fun non-const" << endl; }
void fun(int i) const { cout << "i: " << i << " fun const" << endl; }
};
int main(int argc, char *argv[]) {
Test test;
test.fun(1);
const Test constTest;
constTest.fun(2);
return 0;
}
输出结果:
i: 1 fun non-const
i: 2 fun const
常量成员函数和非常量成员函数都存在的时候,非常量对象将调用非常量成员函数,常量对象将调用常量成员函数。
总结:
1. const修饰的成员函数,不仅限制函数去修改成员变量,同时也可以实现函数的重载
2. const修饰的成员函数,如果没有被重载,那么非const对象和const对象都可以调用;
3. const修饰的成员函数,如果被重载了,非const对象只能调用没有被const修饰的成员函数,const对象也只能调用被const修饰的成员函数。