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语言结 ...
随机推荐
- java jvm 参数 -Xms -Xmx -Xmn -Xss 调优总结
常见配置举例 堆大小设置 JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制.32位系统 下,一般限制在1.5 ...
- UVA_445:Marvelous Mazes
Language:C++ 4.8.2 #include<stdio.h> #include<string.h> #include<ctype.h> int main ...
- MaxCompute如何对SQL查询结果实现分页获取
由于MaxCompute SQL本身不提供类似数据库的select * from table limit x offset y的分页查询逻辑.但是有很多用户希望在一定场景下能够使用获取类似数据库分页的 ...
- celery琐碎笔记
-l 指定日志等级 -n 指定任务名称 -Q 指定任务执行队列 -c 指定启动celery的cpu数量 --logfile 指定日志输出到文件,会输出任务函数里的print,而控制台不会,用于调试. ...
- ssh scp nc
ssh远程连接 ssh root@192.168.111.11 scp数据传输,(secure copy) 1.下载.拉取 scp root@192.168.111.11:/root/database ...
- Java练习 SDUT-3106_小鑫数数儿
小鑫数数儿 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 某天小鑫忽然得到了许多的数字,他很好学,老师给他布置了一个任 ...
- python 操作asdl
#!/usr/bin/env python# -*- coding:utf-8 -*- import win32ras import time,os def Connect(dialname, acc ...
- Jmeter If控制器
"${xxx}"=="1" 或者 "${xxx}"!="2"
- es6 中let与const的简析
1.let 它的作用类似于var,用来声明变量,但是所声明的变量,只在let命令所在的代码块内有效. if(true){ ; let b = ; } document.write(a); docume ...
- Notepad++颜色配置
目前看着比较顺眼的notepad++配置,记录如下: