读书笔记_Effective_C++_条款二十二:将成员变量声明为private
这个条款从字面意思上理解很简单,很多程序都是这样做的,即使作为初学者,也知道该将成员变量声明为private,但有没有想过,为什么要这样做?
为什么public成员变量不行?protected成员变量行不?
举一个简单的例子:
1 class Clothes 2 { 3 public: 4 int price; 5 string name; 6 };
假设有一个衣服的类,里面的成员变量用来描述它的价格和衣服名。将之设为public的话,类外可以直接接触到price成员变量。这样很危险,因为客户端可以直接修改price了,卖衣服的商家就会不开心了。而将price设置成private,像这样:
1 class Clothes 2 { 3 private: 4 int price; 5 string name; 6 public: 7 int GetPrice() 8 { 9 return price; 10 } 11 };
price的访问需要经由GetPrice()的成员函数才能进行,类外客户端不能直接对price进行操作。从这里就可以看到将price设为private的一个好处:可以对访问进行控制,对于一个变量,可以设置它为可读可写(同时提供get和set函数),亦可设置为只读(只提供get函数),甚至可以设置成为只写(只提供set函数)。
书上还说了将price设为private的另一个好处:语法一致性。很多时候程序员在编程的时候都在想到底是Object.price呢,还是Object.price()呢?如果只能通过成员函数访问,就知道后面应该加上小括号了。
将price设为private的第三个好处,就是面向对象的三大基石之一——封装。商家修改了这个类,比如在商店门口公布了打折信息,那么只要在类中这样做:
1 int GetPrice() 2 { 3 return price * 0.9; 4 }
客户端完全不需要作任何修改。封装可以更直观地打一个比方,有两个同学A和B,他们都约自己的朋友去爬山,A约了10个人,而B只约了1个人,不凑巧天下雨了,爬山的计划只能暂时取消,需要通知自己的朋友,这时你想想,是A容易通知呢,还是B容易通知呢?
是的,很明显应该是B好解决问题一些。为什么呢?因为与它发生关系(爬山)的人最少,所以处理起来很方便(一句话,接触越少越容易维护)。这唯一的1个人就好比是成员函数,如果功能变更,只要修改这个成员函数就可以了,而不必修改类外任何代码。
好了,我们总结一下为什么要将成员变量声明为private而不是public的原因:
1. 能够提供语法一致性,写代码的时候能够马上区分要不要加函数括号;
2. 提供更好的访问控制,只读、只写还是可读可写,都容易控制;
3. 封装,减少与外界接触的机会,方便修改和维护。
现在回答下一个问题:为什么protected不行?
如果不存在继承关系,protected的作用与private等同,除了本类之外,其他类或者类外都不能访问,但如果存在继承关系时,protected标识的成员变量,在它的子类中仍可以直接访问,所以封装性就会受到冲击。这时如果更改父类的功能,相应子类涉及到的代码也要修改,这就麻烦了。而如果使用private标识,则根据规则,所有private标识的变量或者函数根本不被继承的,这样就可以保护父类的封装性了,仍可以在子类中通过父类的成员函数进行访问。
书上说了这样一句话:“从封装的角度观之,其实只有两种访问权限:private(提供封装)和其他(不提供封装)。
最后总结一下:
1. 切记将成员变量声明为private,这可赋予客户访问数据的一致性、可细微划分访问控制、允诺约束条件获得保证,并提供class作者以充分的实现弹性
2. protected并不比public更具封装性