const成员函数
- const修饰成员函数的时候,const需要放在成员函数的后面,不能放在一开始,如果放在一开始的话,那么const其实是在修饰成员函数的返回值,而不是在修饰成员函数了

- const成员函数中不能修改成员变量

- 普通成员函数中可以修改成员变量

- 到底要不要使用const去修饰成员函数,就看你的函数中的变量需不需要被修改,如果希望其被修改的话,还是不要给成const,因为给成const的话,就不能去修改他了



const修饰类的成员函数
- 将const修饰的类成员函数称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改

看下面的代码
class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;cout << "Date(int,int,int):" << this << endl;}Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;cout << "Date(Date&):" << this << endl;}Date& operator=(const Date& d){if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}void TestFunc1(){this->_day++;}void TestFunc2()const{this->_day++;}void TestFuncWithConst()const{}void TestFuncWithoutConst(){TestFunc2(); }~Date(){cout << "~Date():" << this << endl;}Date* operator&(){return this;}const Date* operator&()const{return this;}private:int _year;int _month;mutable int _day;
};int main()
{Date d1(2019, 3, 24);const Date d2(2019, 3, 25); cout << &d2 << endl;d1.TestFunc1();d1.TestFunc2();return 0;
}
- 但是有些时候,我还是希望有些值是可以变化的,加上const之后修改成员函数,那么成员函数里面所有的值都不能发生变化了,如果我希望有些值仍然是可以修改的话,那么我可以再某些变量的前面加上mutable,加上mutable之后就表明这个变量可以在const所修饰的成员变量中被修改
请思考下面的几个问题
这两个默认成员函数一般不用重新定义 ,编译器默认会生成。
- const对象可以调用非const成员函数吗?
- 不可以,原因在于用const所修饰的变量本质上是一个常量,所以也就是说常量中的内容是不可以被修改的,但是普通的成员函数,在函数中可以修改当前对象的成员,所以两者是互相矛盾的,所以无法调用

- 非const对象可以调用const成员函数吗?
- 答案是可以的,因为普通类型的对象既可以修改成员变量的值,也可以不去修改成员变量的值,那到底要不要修改,根据情况而定就可以了。

- const成员函数内可以调用其它的非const成员函数吗?
- 是不可以的,因为如果你把一个函数声明为const类型的函数,那么就说明这个函数是只读的,是不可以修改的,而非const的成员函数是可读可写的
- 非const成员函数内可以调用其它的const成员函数吗?
- 可以,因为外层函数的类型是 Date* const:可读可写,而内层函数的类型是const Date* const: 只读,外层可以修改也可以不修改,到底要不要修改,根据具体情况而定就可以了
取地址及const取地址操作符重载
const Date* operator&()const
{return this;
}
int main()
{Date d1(2019, 3, 24);const Date d2(2019, 3, 25); cout << &d2 << endl;d1.TestFunc1();d1.TestFunc2();return 0;
}
class Date
{
public :
Date* operator&()
{return this ;
}
const Date* operator&()const
{return this ;
}
private :int _year ; int _month ; int _day ;
};
- 这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载,比如想让别人获取到指定的内容
程序的运行结果是什么
class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;cout << "Date(int,int,int):" << this << endl;}Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;cout << "Date(Date&):" << this << endl;}Date& operator=(const Date& d){cout << this << "=" << &d << endl;if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}~Date(){cout << "~Date():" << this << endl;}int _year;int _month;int _day;
};Date TestDate(Date& d)
{Date temp(d);temp._day += 1;return d;
}void TestDate()
{Date d1(2019, 3, 24);Date d2(d1);d1 = TestDate(d2);
}int main()
{TestDate();return 0;
}
- 打印结果如下所示:


class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;cout << "Date(int,int,int):" << this << endl;}Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;cout << "Date(Date&):" << this << endl;}Date& operator=(const Date& d){cout << this << "=" << &d << endl;if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}~Date(){cout << "~Date():" << this << endl;}int _year;int _month;int _day;
};Date& TestDate(Date& d)
{Date temp(d);temp._day += 1;return d;
}void TestDate()
{Date d1(2019, 3, 24);Date d2(d1);d1 = TestDate(d2);
}int main()
{TestDate();return 0;
}
- 结果如下所示:

const 重载

- 上面的两个函数是可以形成重载的,之所以可以形成重载是因为有const进行修饰,因为一旦加了const进行修饰的话,两个函数的this指针的类型就不一样了,这也就是为什么两个函数可以形成重载的原因