c++ const关键字详解(上)

        正所谓酒足思淫欲,当衣食无忧的时候自然会产生很多的歪想法,就像当官一样,权力越大,越容易腐败。

        《Effective C++》中第三条:尽量使用const。这就说明使用const是有很大的好处的,const就是把权力尽可能控制一下,这样就会减免很多出bug的机会。因为一个项目不可能只有一个人开发,即使是一个人开发,当涉及到文件多的时候,就会容易出现差错,如果在另外一个文件中修改了一个本不应该修改的变量,就会出现很大的错误。

        const就是将修饰的部分确定为常,所谓常就是不让修改,比如常量,常对象,常指针等等。当我们试图修改这些常量的时候,编译器就会报错,就会阻止错误的发生。下面来看看有哪些const用法。

一、常量

        声明常量的形式:const 数据类型 数据名;

        常量就是不允许修改其值,定义的时候必须赋初始值,不允许再次赋值,这个很好理解。那一个类中也可能会有常数据成员,而我们在类体中往往声明为const,初始化则是在构造函数中,这个时候构造函数的写法就有规定了,看下面的程序:

class Test
{
	public:
		Test(int x, float y):a(x), b(y){} // 如果是Test(int x, int y){a = x; b = y;},编译就会出错
	private:
		const int a; // 声明常数据成员
		float b;
}

int main()
{
	const int t = 10; // 定义常变量(既然是常的怎么又是变量呢哈哈)
	t = 20; // 错误,常量不能再次赋
	Test test(1, 1.1);
}

看着这个构造函数有点别扭,这才是初始化,而后面那种错误的写法就是我们经常写的构造函数,这个只是赋值,但是我们的常数据成员是不能给赋值操作的。所以只能写成第一种写法,而且强烈推荐将构造函数写成这种形式。在main函数里面定义了一个常变量t,定义的时候必须赋初始值,以后都不能再对t进行赋值操作了,否则编译会出错。这里还有个声明和定义的区别,这也是一个比较难理解的概念,类体里面是声明了一个常数据成员,而main函数里则是定义了一个常变量,查查资料好好体会一下。

二、常对象

        声明常对象的两种形式:const 类名 对象名(参数列表);

                                                    类名 const 对象名(参数列表);

        什么是常对象呢,就是对象不允许改变,也就是说,不能修改常对象的任何成员变量,当一个对象定义为常对象的时候,任何修改其成员变量的操作都会报编译错误的。看看下面这个程序:

#include<iostream>
using namespace std;

class Test{
	public:
		Test(int x, float y):a(x), b(y){} // 推荐这种写法
		void print()
		{
			x = 10; // 对x进行赋值
			cout << "x:" << x << ", y:" << y << endl;
		}
	private:
		int a;
		float b;
}

int main()
{
	Test test1(1, 1.1);
	test1.print();
	const Test test2(2, 2.2);
	test2.print(); // 编译出错,因为print()方法中有修改test2的成员变量
}

有人说,我自己写的程序干嘛没事在print()函数里面写个修改x值的代码啊,吃饱了撑着。说的对,正常情况下不会这样,但这也只是你一厢情愿罢了,你的程序就允许这样写,而且这样写这一行是完全没问题的,这就为出错埋下了伏笔。但有时候确实需要这样写,比如我就要每次输出x都为10,这就要看自己程序的必要性了。所以我们将这一行删掉,不改变常对象的成员变量就OK了,所以我们定义对象的时候,如果不需要修改它的成员变量的时候就定义为常对象。这个问题是解决了,但是我们改了再编译一次,还是会报错,那就是常对象只能调用常成员函数。

三、常成员函数

        声明常成员函数的形式:返回值类型 成员函数名(形参列表) const;

        上面提到的,当test2调用print()函数的时候就会报错,这是因为test2是常对象,而print()函数是非常成员函数,所以不能调用。为啥嘞,定义成常对象,当然不想对象的成员变量被修改,非常成员函数是允许修改该类的成员变量的,所以二者冲突了。看下面这个程序:

#include<iostream>
using namespace std;

class Test
{
	public:
		Test(int x, float y):a(x), b(y){}
		void print() const
		{
			x = 10; // 编译出错
			cout << "x:" << x << ", y:" << y << endl;
		}
		void setA(int x)
		{
			a = x;
		}
	private:
		int a;
		float b;
}

int main()
{
	const Test test1(1, 1.1);
	test1.print();
	test1.setA(10); // 编译错误,常对象不能调用非常成员函数
	Test test2(2, 2.2);
	test2.print(); // 非常对象可以调用常成员函数
	test2.setA(10);
}

上面程序中,x=10这行编译就会出错,因为函数为const型,所以是不允许修改类的成员变量的,所以当我们的函数没有涉及到成员变量的赋值操作,将其声明为const型是不是更安全呢。test2是非常对象,即可以调用非常成员函数,也可以调用常成员函数,这个很好理解的。


        还有指向对象的常指针,指向常对象的指针和常形参,后面再分析。

c++ const关键字详解(上),布布扣,bubuko.com

c++ const关键字详解(上)

上一篇:python 使用CppHeaderParser库 根据c++头文件生成html说明文档表格


下一篇:【Python实战14】继承Python内置的list