mutable关键字

来源:互联网 发布:2016淘宝刷流量 编辑:程序博客网 时间:2024/06/06 02:08
前言

mutable的字面意思是,易变的。它在C++中的作用是让一个常函数可以修改mutable修饰的变量。

常成员函数的声明原则

在类中声明成员函数时,如果这个函数不会改变对象的状态,那么我们就应该用const去修饰它,将其声明为常成员函数。那么怎样才算是改变对象状态呢?我以前只是简单的认为,只要修改了成员变量就是改变了对象状态,但是这种想法太片面了。

还有一种特殊的情况,如果一个函数会改变某个成员对象的值,但未必会改变对象状态。这是因为,并不能够完全根据成员对象的值是否被改变来判定,而应当根据这个对象对外的接口函数所反应的信息来判断。如果对一个成员函数的调用,不会使其后对该对象的成员函数的调用的结果发生变化,那么就可以认为这个成员函数的调用不会改变对象状态。这个原则,只是从经验的角度得出来的,对于具体物理意义的对象,还是应当有更具体的判别方式。

来看看下面这个例子

class Line {public:    explicit Line(const Point &p1, const Point &p2)        : p1(p1), p2(p2), len(-1) {}    double getLen();private:    Point p1, p2;    double len;};double Line::getLen() {    if (len < 0) {        double x = p1.getX() - p2.getX();        double y = p1.getY() - p2.getY();        len = sqrt(x*x + y*y);    }    return len;}

Line类的getLen函数用于计算两点之间的长度,并将结果保存到变量len中。这样可以避免以后重复计算。从经验的角度看,在它调用多次后,得到的都是相同的结果,因此不会改变对象的状态。既然是这样,那就和之间的原则矛盾了,既然不会改变对象状态,就应当将其声明为常成员函数,但是语法上不允许,因为它终究是改变了len的值,虽然只有一次。为此,C++提供了一个解决方法,那就是关键字——”mutable”。通过它进行修饰后,即使是常成员函数也可以修改它们的值。于是可以把上面的代码改成如下形式:

class Line {public:    explicit Line(const Point &p1, const Point &p2)        : p1(p1), p2(p2), len(-1) {}    double getLen() const;private:    Point p1, p2;    mutable double len;};double Line::getLen() const{    if (len < 0) {        double x = p1.getX() - p2.getX();        double y = p1.getY() - p2.getY();        len = sqrt(x*x + y*y);    }    return len;}

使用了mutable修饰后,就可以将getLen函数声明为常成员函数了。
其实mutable不只允许在常成员函数中修改被它修饰的数据成员,“常对象的成员对象被视为常对象”这一语言原则,对mutable修饰的成员并不适用。被mutable修饰的成员对象在任何时候都不会被视为常对象,这是mutable更一般的含义。尽管mutable能够很好的解决上例中的问题,但绝对不能滥用,否则会破坏const形成的语言保护机制。也就是说,一定要确定存在常成员函数要改变一个成员对象,而且对该成员函数的调用确实不会改变对象状态。

0 0
原创粉丝点击