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;  //保存一个计数值,用于记录成员函数被调用的次数
}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值