在c++primer一书中,介绍类的时候提到这样“将关键字const加在形参列表之后,就可以将成员函数声明为常量:
double avg_private() const;
const 成员不能改变其所操作的对象的数据成员”
先写一个Person类
class Person
{
public:
Person(){}
Person(string str1,string str2):name(str1),addr(str2){}
string getName()const
{
return name;
}
string getAddr()const
{
return addr;
}
int show(Person per) const;//定义与声明都要用const
void sayHello();
private:
string name;
string addr;
};
定义了一个person类,定义了两个成员,人的名字和地址。两个构造函数,一个不带参数,一个带参数。另外定义了三个常成员函数,getName()和getAddr()获取人的名字和地址,一个显示人信息的函数show(),还有测试函数sayHello();
那么在声明或定义常成员函数的时候,为什么把const写在函数调用后面呢,因为若是const限定符在函数前面,那么就是说明函数的返回值是const型,这样跟我们声明或定义常成员函数的初衷就违背了。
像这样
string getAddr()const//定义常成员函数,函数内不能改变其所操作对象的数据成员
const string getAddr()//函数返回一个const型变量
类的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员(准确地说是非静态数据成员)作任何改变,这是定义常成员函数的一个好处。在我们设计类的时候,一个基本原则也就是对于不改变类数据成员的成员函数都要在后面加 const,而对于改变类数据成员的成员函数不能加 const。
下面的定义常成员函数就错误了
string getName()const
{
//name = "xxx";//这样改变了与对象绑定成员变量的值 错误
return name;
}
那么下面的调用是正确的
Person per("bob","america");
cout<<per.getName()<<endl;//非const对象调用const成员函数 正确
cout<<per.getAddr()<<endl;//同上 正确
per.sayHello();//非const对象调用非const成员函数 正确
当定义一个const对象后情况是这样的
const Person per("james","china");
cout<<per.getName()<<endl;//const对象调用const成员函数 正确
cout<<per.getAddr()<<endl;//同上 正确
per.sayHello();//const对象调用非const成员函数 错误
这也就是定义常成员函数的另一个好处,就是常量(即 const)对象可以调用 const 成员函数,而不能调用非const修饰的函数。正如非const类型的数据可以给const类型的变量赋值一样,反之则不成立。
其实总结一下,记住这一条就可以了,const对象不能调用非const成员函数。但构造函数和析构函数对这个规则例外,它们从不定义为常量成员,但可被常量对象调用(被自动调用)最后把整个完整代码也贴一份吧
#include <iostream>
#include <string>
using namespace std;
class Person
{
public:
Person(){}
Person(string str1,string str2):name(str1),addr(str2){}
string getName()const
{
return name;
}
string getAddr()const
{
return addr;
}
int show(Person per) const;//定义与声明都要用const
void sayHello();
private:
string name;
string addr;
};
int Person::show(Person per) const//定义与声明都要用const
{
cout<<per.name<<" comes from "<<per.addr<<endl;
return 0;
}
void Person::sayHello()
{
cout<<"Hello world"<<endl;
}
//非常量成员函数不能被常量成员对象调用
//但构造函数和析构函数对这个规则例外,它们从不定义为常量成员,但可被常量对象调用(被自动调用)
void getInfo(const Person& person)
{
cout<<person.getName()<<endl;//常对象person调用const成员函数getName
cout<<person.getAddr()<<endl;//常对象person调用const成员函数getAddr
}
int main()
{
// Person per("bob","america");
// getInfo(per);
// per.show(per);
/* Person per("bob","america");
cout<<per.getName()<<endl;//非const对象调用const成员函数 正确
cout<<per.getAddr()<<endl;//同上 正确
per.sayHello();//非const对象调用非const成员函数 正确
*/
const Person per("james","china");
cout<<per.getName()<<endl;//const对象调用const成员函数 正确
cout<<per.getAddr()<<endl;//同上 正确
//per.sayHello();//const对象调用非const成员函数 错误
return 0;
}