C++那些细节--const与函数

一.简介

const是C++中灰常灰常强大的关键字。const--constant的缩写,简单理解就是不变的意思,它的所有功能都是限定我们修改某个变量。虽然我们最熟悉的是const常量,但是这并不是const最有用的部分。const和函数碰撞在一起的时候,才能激发出const真正能力。

下面看一下const修饰函数本身,修饰函数参数,修饰函数返回值时,都能带来哪些效果。

二.const修饰函数本身


const修饰函数本身,这个是最灵活,也是最复杂,涉及到点最多的地方!!

1.const修饰函数的意义


C++中成员函数后面经常看到const关键字修饰,这是一种很好的习惯吗,在我们的函数不需要修改对象的内容时,果断给它加上const修饰。《Effective C++》中说过,尽量使用const,可以减少很多不必要的麻烦。那么const修饰成员函数究竟有什么作用呢?

a.最主要的就是防止成员函数修改成员变量(非静态成员变量):试想一下,本来我想通过这个函数来输出一下log的,但是一不小心,将判断成员变量的==写成了=,那么如果这个函数是const的,编译的时候会立刻报错的,而如果这个函数不是const的,那么这个函数就会将成员变量修改,(VS貌似会有warning),这将是一个灰常难以发现的bug。所以,当一个函数不应该修改成员变量的时候,果断将其设置为const的。
b.成员函数是不是用const修饰的,也可以很方便的帮助我们理解代码:让我们知道哪些内容可以修改对象成员的变量,哪些不可以,进而更好的帮我们理对象的功能。
c.const成员函数使我们可以操作const对象:因为非const成员函数是不能被const对象调用的,只有被声明为const的成员函数才能被一个const类对象调用。这也是C++通过指针或者引用传递参数的基础之一。

2.const修饰函数的使用方法


其实使用const修饰函数很简单,只需要在函数后面加上一个const即可。不过有一点要注意,当函数定义和声明分开的时候,如果声明加了const,那么定义的时候也需要加上const,这一点与virtual关键字不同。
简单的一个例子:
// C++Test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;



class Base
{
private:
	int num;
public:
	Base(int n)
	{
		num = n;
	}

	virtual void Show() const ;
};

void Base::Show() const
{
	cout<<"base show: "<<num<<endl;
}



 
int _tmain(int argc, _TCHAR* argv[])
{
	Base* base1 = new Base(1);
	
	base1->Show();

	system("pause");
	return 0;
}
结果:
base show: 1
请按任意键继续. . .

3.加const和不加const表示不同的函数


我们还是用virtual关键字作为比较,当这个类被继承之后,原本为virtual的函数,在子类中即使不写virtual,它仍然是virtual的。但是,我们如果不写const的话,会发生什么呢?这可是一个灰常有意思的实验,瞪大眼睛看好啦!!!
// C++Test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;


//基类,包含一个virtual函数,const类型
class Base
{
protected:
	int num;
public:
	Base(int n)
	{
		num = n;
	}

	virtual void Show() const ;
};

void Base::Show() const
{
	cout<<"base show: "<<num<<endl;
}


//派生类,派生了Show,但是!!!忘记写const了
class Derived : public Base
{
public:
	Derived(int n) : Base(n)
	{

	}
	void Show();
};

void Derived::Show() 
{
	cout<<"derived show: "<<num<<endl;
}



 
int _tmain(int argc, _TCHAR* argv[])
{
	//基类调用基类,base show木有问题
	Base* base1 = new Base(1);
	base1->Show();

	//基类掉子类,应该触发多态,derived show会被调用吗?
	Base* derived1 = new Derived(2);
	derived1->Show();

	system("pause");
	return 0;
}
结果:
base show: 1
base show: 2
请按任意键继续. . .

virtual函数,正常应该触发多态的,但是!!并没有出现我们想要的结果!!!derived1调用的仍然是基类的Show方法。为什么会出现这种情况呢?原因很简单,virtual并没有失效,而是因为我们根本就没有覆写Show()const函数!!!换句话说,我们在子类又创建了一个非const版本的Show函数!而我们调用的时候,直接调用了基类的Show,跟virtual没有半毛钱关系。

virtual等其他关键字,修饰之后,函数仍然是原来的函数,定义一个不带这个关键字的函数就会报错说重定义。但是,const关键字和它们不一样,有const和没有const的函数是两个不同的函数,它们是可以共存的!!
上面的例子主要就是说明const版本的成员函数和非const版本的成员函数并不相同,说实话绕的有点儿远,不过这个确实是一个非常容易犯的错误,而又非常非常难以发现!本人亲测,在VS默认警告等级上,并没有给出警告。将警告等级调高之后,编译器才给出了警告:
  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值