C++中常量成员函数的含义
C++中常量成员函数的含义
本文内容来源:《C++必知必会》
使用常量成员函数可以改变对象的逻辑状态,虽然对象的物理状态没有发生改变。考虑如下代码,它定义了一个类X:
class X{
public:
X():buffer_(0),isComputed_(false){}
//...
void setBuffer(){
int *tmp = new int[MAX];
delete [] buffer_;
buffer_ = tmp;
}//setBuffer void modifyBuffer(int index, int value) const{
buffer_[index] = value; //Valid but not suggested!
}//end of modifyBuffer int getValue() const{
if( !isComputed_){
computedValue = expensiveOperation(); //Error!
isComputed_ =true; // Error!
}
return computedValue_;
}//end of getValue
private:
static int expensiveOperation();
int *buffer_;
bool isComputed_;
int computeValue_;
}
setBuffer函数必须是非常量的,因为它要修改其所属的X对象的一个数据成员。然而,modifyBuffer可以被合法地被标为常量,因为它没有修改X对象,它只是修改X的buffer_成员所指向的一些数据。这种做法是合法的,但是很不道德。
有时一个被声明为常量的成员函数必须要修改其对象,这常见于利用"lazy evaluation"机制来计算一个值时,换句话说,只有当第一次提出请求,才计算值,目的在于在该请求根本没有发出的其余情形下,让程序运行得更快。在这种情况下会有一个进行转型犯错的诱惑,为的是能够让事情变得更好,即将该成员函数声明为常量。
int getValue() const{
int (!isComputed_){
X *const aThis = const_cast<X *const>(this);
aThis->computedValue = expensiveOperation();
aThis->isComputed_ = true;
}
return computedValue_;
}
class X{
public:
//...
int getValue() const{
int (!isComputed_){
computedValue = expensiveOperation();
isComputed_ = true;
}
return computedValue_;
}
private:
mutable bool isComputed_; //现在可以修改了。
mutable int computedValue_; //现在可以修改了。
}
类的非静态数据成员可以声明为mutable,这将允许它们的值可以被该类的常量成员函数(当然也包括非常量成员函数)修改,从而允许一个“逻辑上为常量”的成员函数被声明为常量,虽然其实现需要修改该对象。
以下例子可以解释函数重载解析是如何区分一个成员函数的常量和非常量版本的。
class X{
public:
//...
int &operator[] (int index);
cost int &operator[](int index) const;
}; int i = 12;
X a;
a[7] = i;// this 是 X *const,因为a是非常量
const X b;
i = b[i]; // this 是 const X *const, 因为b 是常量
考虑如下具有两个常量参数的非成员二元操作符
如果决定声明一个与此重载操作符对应的成员形式的对应物,应该将其声明为常量成员函数,此目的是为了保持左实参的常量性质。
class X{
public:
//...
X operator+(const X &rightArg); // 左边的参数是非常量
X operator+(const X &rightArg) const; //左边的参数是常量
};
规则:
1.常量成员函数不修改对象。
2.常量成员函数在定义和声明中都应加const限定
3.非常量成员函数不能被常量成员函数调用,但构造函数和析构函数除外。
4.常量(const对象)对象只能调用常量成员函数。(const对象的数据成员在对象寿命周期内不能改变,因此其只能调用常量成员函数)。
意义:
1.使成员函数的意义更加清楚,将成员函数分修改对象和不修改对象两类。
2.增加程序的健壮性,常量成员函数企图修改数据成员或调用非常量成员函数,编译器会指出错误。
原因:
对于X类型的非常量成员函数而言,其this指针的类型是 X * const,该指针自身是常量;但是对于X类型的常量成员函数而言,其this指针的类型是const X * const,是一个常量指针。
<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">
C++中常量成员函数的含义的更多相关文章
- C++中的const成员函数(函数声明后加const,或称常量成员函数)用法详解
http://blog.csdn.net/gmstart/article/details/7046140 在C++的类定义里面,可以看到类似下面的定义: 01 class List { 02 priv ...
- C++ 之 常量成员函数
类的常量成员函数 (const member function), 可以读取类的数据成员,但是不能修改. 1 声明 1.1 const 关键字 在参数列表后,加 const 关键字,声明为常量成员 ...
- C++ const常量对象、常量成员函数和常引用
01 常量对象 如果不希望某个对象的值被改变,则定义该对象的时候可以在前面加const关键字 class CTest { public: void SetValue() {} private: int ...
- 总结C++中取成员函数地址的几种方法
这里, 我整理了4种C++中取成员函数地址的方法, 第1,2,4种整理于网上的方法, 第3种cdecl_cast是我自己想到的. 其中, 第4种(汇编)的方法不能在VC6上编译通过. 推荐使用第1,2 ...
- 【转】总结C++中取成员函数地址的几种方法
转自:“http://www.cnblogs.com/nbsofer/p/get_member_function_address_cpp.html” 这里, 我整理了4种C++中取成员函数地址的方法, ...
- C++官方文档-常量成员函数
#include <iostream> using namespace std; class MyClass { public: int x; static int n; const in ...
- C++(十六) — 类中引用成员函数、命名空间的使用
1.为什么类中引用成员函数? 类将属性和方法做了封装.类是一种数据类型,也就是:固定大小内存块的别名. 类的定义是一个抽象的概念,定义时不分配内存,当用类定义对象时,才分配一个固定大小的内存块. 此时 ...
- 【Java.Regex】使用正则表达式查找一个Java类中的成员函数
代码: import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; imp ...
- 在C语言结构体中添加成员函数
我们在使用C语言的结构体时,经常都是只定义几个成员变量,而学过面向对象的人应该知道,我们定义类时,不只是定义了成员变量,还定义了成员方法,而类的结构和结构体非常的相似,所以,为什么不想想如何在C语言结 ...
随机推荐
- Python学习之路11☞异常处理
一 错误和异常 part1:程序中难免出现错误,而错误分成两种 1.语法错误(这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正) #语法错误示范一 if #语法错误示范二 de ...
- 尖峰7月线上技术分享--Hadoop、MySQL
7月2号晚20:30-22:30 东大博士Dasight分享主题<大数据与Hadoop漫谈> 7月5号晚20:30-22:30 原支付宝MySQL首席DBA分享主题<MySQL ...
- Java8 日期、时间操作
一.简介 在Java8之前,日期时间API一直被开发者诟病,包括:java.util.Date是可变类型,SimpleDateFormat非线程安全等问题.故此,Java8引入了一套全新的日期时间处理 ...
- Xcode无法退出,报错提示 The document “xxx.h” could not be saved. The file doesn’t exist.
记录一个问题 场景:Xcode编辑一个工程时直接在工程内部修改了某个目录的文件夹名字,而后删除了其下的某 .h.m 文件 之后总是提示上述错误且无法强制退出Xcode,clean等操作基本没用 查找本 ...
- Java练习 SDUT-1140_面向对象程序设计上机练习一(函数重载)
面向对象程序设计上机练习一(函数重载) Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 利用数组和函数重载求5个数最大值 ...
- Python3.6正向解析与反向解析域中主机
公司最近接手的一家跨国企业的项目,该企业单域.多站点,且遍布美国.巴西.日本.东京.新加坡等多个国家,服务器及客户端计算机数量庞大.由于处理一些特殊故障,需要找出一些不在域中的网络设备及存储.NBU等 ...
- Hbase数据模型物理视图
- 【[Offer收割]编程练习赛9 D】 矩阵填数
[题目链接]:http://hihocoder.com/problemset/problem/1480 [题意] [题解] 这是一道杨氏矩阵的题; 一个固定形状的杨氏矩阵的种类个数; 等于这个杨氏矩阵 ...
- 2019南昌网络赛-I. Yukino With Subinterval 线段树套树状数组,CDQ分治
TMD...这题卡内存卡的真优秀... 所以以后还是别用主席树的写法...不然怎么死的都不知道... 树套树中,主席树方法开权值线段树...会造成空间的浪费...这道题内存卡的很紧... 由于树套树已 ...
- Pointers and Arrays_4
1.编写程序expr,以计算从命令行输入的逆波兰表达式的值,其中每个运算符或操作数用一个单独的参数表示.例如,命令expr 2 3 4 + * 将计算表达式2×(3+4) 的值. #include & ...