本文主要是介绍const修饰类成员和类对象、const修饰成员函数构成重载、可变数据成员mutable、,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
其他文章:C++中const成员函数和非const成员函数的重载_梦心之魂的博客-CSDN博客
const修饰数据成员、成员函数
1.const 修饰数据成员:初始化位置可以在参数列表中,新版本也可以在声明位置直接初始化,被const修饰的数据成员,不能被修改
2. const 修饰成员函数:const位置在函数声明之后、实现体之前如果分.h和.cpp的话,要求在定义和声明处都要有const修饰,是从函数的层面,不修改数据。
意义:const函数承诺,不会修改数据成员(无论数据成员有没有const),能访问const 和非const数据成员,但不能修改数据成员,const数据成员只能访问const成员函数,因为只有const函数才能保证不会修改
作用:提供对于const对象调用时的支持
#include "stdafx.h"
#include <iostream>
using namespace std;class A
{
public:A(int v = 0):val(v){}//const 只能放在函数后面 因为 const void 和 void const //都是修饰返回类型void的void dis() const{cout << val << endl;//val = 200; const的数据成员一定改不了//x=200; const函数承诺不会修改数据成员(无论加不加const)//print(); 也不可以间接去修改print(); //可以访问const成员函数}void dis(){cout << "void dis() " << endl;}void print() //this指针的类型是A*{x = 100;y = 200;}void print() const //this指针的类型是const A*{cout << "void print() const" << endl;}
private:const int val; //新版本修饰数据成员可以在这初始化int x, y;
};int _tmain(int argc, _TCHAR* argv[])
{A a(5); //非const类对象a.dis(); //有非const的成员函数优先 其次调用const成员函数const A a1(5); //const类对象a1.print();a1.dis(); //const对象只能调用const函数return 0;
}
const修饰成员函数与普通成员函数构成重载
在函数重载中有一种特殊的函数重载方法,那就是const修饰成员函数的重载,对于const修饰的类对象,是从对象的层面,不修改数据,只能调用const成员函数。
const对象与const成员函数的调用规则:
1.const对象 只能调用const成员函数
2.非const成员对象,优先调用非const成员函数,若没有,则可调用const成员函数
原因:按照函数重载的定义,函数名相同而形参表有本质不同的函数称为重载。在类中,由于隐含的this形参的存在,const版本的成员函数使得作为形参的this指针的类型变为指向const对象的指针,而非const版本的使得作为形参的this指针就是正常版本的指针。此处是发生重载的本质。重载函数在最佳匹配过程中,对于const对象调用的就选取const版本的成员函数,而普通的对象调用就选取非const版本的成员函数。(注:this指针是一个const指针,地址不能改,但能改变其指向的对象或者变量)
const修饰的成员函数返回类型为*或者&时,最好再使用const来修饰返回值
我们已经知道const修饰成员函数的作用之一就是保证不会修改类中的数据成员,那么如果这个函数将数据成员的*和&类型作为返回值时,我们却可以间接的修改其数据成员,大多情况下,这与我们的期望并不相符,所以在返回类型为引用或指针的const成员函数中,最好再使用const来修改其返回值。
例如String类中我们为它提供一个下标操作符([ ])以读写指定位置的字符,只要了解过C++的操作符重载的语法,很快就可以写出下面这个[]操作符重载函数
char& operator[](int posion) // function_1{return data[posion];};
注意,这里该函数的返回值为一个引用,否则str[0] = 'c'这样的语句就会不合法,因为str[0]将是一个左值。那么,是否提供这样一个function_1就足够了呢?看下面这段代码:
const String str= "She";
char c = str[0]; // 错误!编译提示:error C2678: 二进制“[” : 没有找到接受“const String”类型的左操作数的运算符(或没有可接受的转换)
很显然,我们必须还要为const String提供一个const版本的opeartor[],因为const修饰的类对象只能调用const修饰的成员函数。
char& operator[](int posion) const
{return data[posion];
}
这样,当使用const的String对象使用[]操作符时,便会调用该const的重载版本。但是,这样就OK了嘛?虽然上面的那段代码没有问题了,但是其中却隐藏了一个陷阱,看如下代码:
const String str = "She";
str[0] = 'T';
上面这段代码可以编译,运行通过,str变为了"The"!而str声明为const的!!现在,你应该知道了,对于const的该操作符重载函数其返回值也应该是const的,否则就会出现可以通过其修改const对象的漏洞。为了给String提供一个[]操作符来读写指定位置的字符,需要提供如下两个函数,以分别对非const String对象和const String对象提供支持
char& operator[](int posion)
{return data[posion];
};const char& operator[](int posion) const
{return data[posion];
}
可变数据成员mutable
有时会发生这样一种情况,我们希望能修改类的某个数据成员,即使是在一个const成员函数内,可以通过在变量的声明加入mutable关键字做到这一点,因此它可以使const成员函数可以改变一个可变成员的值,一个可变数据成员永远不会是const
class Screen
{
public:void some_member() const;
private:mutable size_t access_ctr; //即使在一个const对象内也能被修改
};void Screen::some_member() const
{++access_ctr; //保存一个计数值,用于记录成员函数被调用的次数
}
这篇关于const修饰类成员和类对象、const修饰成员函数构成重载、可变数据成员mutable、的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!