本文转自http://blog.csdn.net/whyglinux/article/details/602329

类的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员(准确地说是非静态数据成员)作任何改变。

在设计类的时候,一个原则就是对于不改变数据成员的成员函数都要在后面加 const,而对于改变数据成员的成员函数不能加 const。所以 const 关键字对成员函数的行为作了更加明确的限定:有 const 修饰的成员函数(指 const 放在函数参数表的后面,而不是在函数前面或者参数表内),只能读取数据成员,不能改变数据成员;没有 const 修饰的成员函数,对数据成员则是可读可写的。

除此之外,在类的成员函数后面加 const 还有什么好处呢?那就是常量(即 const)对象可以调用 const 成员函数,而不能调用非const修饰的函数[但是非const对象既可以调用const成员函数,也可以调用非const成员函数!!!]。正如非const类型的数据可以给const类型的变量赋值一样,反之则不成立。

请看下面一个完整的例子,然后我再作一些说明。

#include <iostream>
#include <string>
using namespace std; class Student {
public:
Student() {}
Student( const string& nm, int sc = 0 )
: name( nm ), score( sc ) {} void set_student( const string& nm, int sc = 0 )
{
name = nm;
score = sc;
} const string& get_name() const
{
return name;
} int get_score() const
{
return score;
} private:
string name;
int score;
}; // output student's name and score
void output_student( const Student& student )
{
cout << student.get_name() << "/t";
cout << student.get_score() << endl;
} int main()
{
Student stu( "Wang", 85 );
output_student( stu );
}

  

设 计了一个类 Student,数据成员有 name 和 score,有两个构造函数,有一个设置成员数据函数 set_student(),各有一个取得 name 和 score 的函数 get_name() 和 get_score()。请注意 get_name() 和 get_score() 后面都加了 const,而 set_student() 后面没有(也不能有const)。

首先说一点题外话,为什么 get_name() 前面也加 const。如果没有前后两个 const 的话,get_name() 返回的是对私有数据成员 name 的引用,所以通过这个引用可以改变私有成员 name 的值,如

  Student stu( "Wang", 85 );
stu.get_name() = "Li";

  

即把 name 由原来的 "Wang" 变成了 "Li",而这不是我们希望的发生的。所以在 get_name() 前面加 const 避免这种情况的发生。

那么,get_name() 和 get_score() 这两个后面应该加 const的成员函数,如果没有 const 修饰的话可不可以呢?回答是可以!但是这样做的代价是:const对象将不能再调用这两个非const成员函数了。如

const string& get_name(); // 这两个函数都应该设成 const 型
int get_score();
void output_student( const Student& student )
{
cout << student.get_name() << "/t"; // 如果 get_name() 和 get_score() 是非const成员函数,这一句和下一句调用是错误的
cout << student.get_score() << endl;
}

  

由 于参数student表示的是一个对const Student型对象的引用,所以 student 不能调用非const成员函数如 set_student()。如果 get_name() 和 get_score() 成员函数也变成非const型,那么上面的 student.get_name() 和 student.get_score() 的使用就是非法的,这样就会给我们处理问题造成困难。

因此,我们没有理由反对使用const,该加const时就应该加上const,这样使成员函数除了非const的对象之外,const对象也能够调用它。

类中用const限定的成员函数的更多相关文章

  1. C++ 空类,默认产生哪些成员函数

    C++ 空类,默认产生哪些成员函数.     默认构造函数.默认拷贝构造函数.默认析构函数.默认赋值运算符 这四个是我们通常大都知道的.但是除了这四个,还有两个,那就是取址运算符和 取址运算符 con ...

  2. C++类内存布局图(成员函数和成员变量分开讨论)

    一.成员函数 成员函数可以被看作是类作用域的全局函数,不在对象分配的空间里,只有虚函数才会在类对象里有一个指针,存放虚函数的地址等相关信息. 成员函数的地址,编译期就已确定,并静态绑定或动态的绑定在对 ...

  3. const对象 不能调用非const修饰的成员函数

    class class UIRect:public RECT { public: UIRect(LONG leftT = 0, LONG topT = 0, LONG rightT = 0, LONG ...

  4. const用在成员函数之后的情况

    常成员函数         使用const关键字进行说明的成员函数,称为常成员函数.只有常成员函数才有资格操作常量或常对象,没有使用const关键字说明的成员函数不能用来操作常对象.常成员函数说明格式 ...

  5. C#中Stack&lt;T&gt;类的使用及部分成员函数的源代码分析

    Stack<T>类 Stack<T> 作为数组来实现. Stack<T> 的容量是 Stack<T> 能够包括的元素数. 当向 Stack<T&g ...

  6. C++ 友元 (全局函数做友元) (类做友元) (成员函数做友元)

    1 //友元 全局函数做友元 2 /* 3 #include <iostream> 4 #include <string> 5 using namespace std; 6 7 ...

  7. String类的四个默认成员函数

    优化版的拷贝构造函数,先创建一个暂时实例tmp,接着把tmp._ptr和this->_ptr交换,因为tmp是一个局部变量.程序执行到该函数作用域外,就会自己主动调用析构函数.释放tmp._pt ...

  8. C++中const对象和非const对象调用成员函数问题

    一.类MyClass 二.主函数调用 三.结果

  9. python类内部调用自己的成员函数必须加self

    class A: def a(self): print("hello world") def b(self): return self.a() 上面的self.a()中self是不 ...

随机推荐

  1. ssm控制输出sql(二)

    望时高科联通log4j # DEBUG,INFO,WARN,ERROR,FATAL LOG_LEVEL=DEBUG ---------这里对应sql的级别 log4j.rootLogger=${LOG ...

  2. WCF服务跟踪

    如果在开发过程中,WCF服务出现问题,我们可以通过服务引用,然后直接断点调试进去.然而,对于已经发布的服务,出现错误时,寻找错误信息会变得麻烦. 幸好,微软提供了服务跟踪查看器工具 (SvcTrace ...

  3. xmpp即时通讯的笔记(摘抄)

    xmpp的使用: 即时通讯 instant messaging(IM) :  -->实时收发信息! 即时通讯相关软件: **QQ,MSN,GoogleTalk,AIM,Jabber(XMPP别名 ...

  4. [Android Pro] CountDownTimer倒计时

    定时执行在一段时候后停止的倒计时,在倒计时执行过程中会在固定间隔时间得到通知(译者:触发onTick方法),下面的例子显示在一个文本框中显示一个30s倒计时: new CountdownTimer(3 ...

  5. mongodb 3.2 用户权限管理配置

    使用mongodb 有段时间了,由于是在内网使用,便没有设置权限,一直是裸奔. 最近有时间,研究了下mongodb 3.2 的用户权限配置,网上有许多用户权限配置的文章,不过大多是之前版本,有些出入, ...

  6. vs c# int & int32

    在vs c#中,int就等价于int32, 所以通常也是使用int32 当在统计总数时,最好使用int32,int16数值范围太小,如果超出,就会变成随机数.

  7. hosts文件修改之后立刻刷新

    最近因为项目的需要,总是修改hosts文件,每次修改之后都要重启浏览器,总结下刷新的方式 window下,hosts文件位置:C:\windows\system32\drivers\etc\hosts ...

  8. 通过NSString初始化OC类

    NSString *className = self.classNames[indexPath.section][indexPath.row];    BaseMapViewController *s ...

  9. [Android]在代码混淆中关闭 Log

    -assumenosideeffects class android.util.Log{ public static *** d(...); public static *** e(...); }

  10. CLR via C#(03)- 对象创建和类型转换

    一. 创建对象 CLR要求用new操作符创建对象,这个操作符在编译时产生的IL指令为newobj.例如: Student XiaoJing=new Student(“XiaoJing”,”1986”) ...