实用经验 65 将成员变量声明为private

本文探讨C++中成员变量访问权限的重要性,尤其是private的使用。将成员变量声明为private可以提供精确的访问控制、增加封装性和提供语法一致性。private变量可以通过接口函数访问,增强了类的灵活性和安全性。而public变量可能导致数据保护不足,影响程序的稳定性和可维护性。因此,推荐将数据成员声明为private以提高代码质量。
摘要由CSDN通过智能技术生成

在C++程序设计中,只要有一定程序设计经验的程序员。一般都有这样的意识:尽量将成员变量声明为private成员。本实用经验就讲述一下关于成员变量的访问权限。我们都知道成员变量的访问权限有三种:public访问权限、private访问权限、protected访问权限。

访问权限说明

  • public访问权限是权限最高的一种权限。如果将一个变量声明为public访问权限,用户可随意访问和设置此成员变量。这在一定程度上增加了程序的安全风险(本实用经验后续部分将讨论)。
  • private访问权限是权限最低一种权限。将变量声明为private访问权限,如果不提供控制接口,用户无法访问和设置此变量,这可在一定程度上提供安全性。
  • protected权限介于public和private之间。在成员访问方面其呈现出private权限,在继承机制的派生类中其呈现出public访问权限。

C++中所谓数据的访问权限即我们通常所述的数据的封装,其也是C++区别于C的重要标准。C语言中数据仅仅是配角,其服务于过程设计。然而C++则不然,数据是C++程序设计的核心,是主角。这种思想最具特色的就是struct和class:struct提供无封装的数据访问权限,class可提供我们自定义的数据访问权限。

在C++程序设计时,思考和创造全部围绕着数据进行。这也是从C程序设计到C++程序设计的重要转变。按照这种设计理念,大多数情况下,我们建议将数据成员声明为private。现在我们就分析将数据声明为private有什么优势;为何又不将数据声明为public访问权限?

1.提供精确的访问控制

我们思考,如果将数据声明为public会给我们带来什么样的影响。我们都知道的,如果一个数据声明为public权限,每个人都可以按照自己的期望,随意的访问和修改它。这回给我们带来什么呢?第一、数据失去了保护和封装,这种情况下class和struct几乎无异。第二、数据成员采用struct形式访问,如果class中这个数据成员发生了变化,这将导致整个程序只要使用其的地方,都需要进行修改。第三、外部对class内部数据的访问class无法感知。

但是,如果我们把数据成员声明为private,就可以将数据隐藏起来。然后提供数据的set和get访问控制函数。这样就可实现精确的数据访问可读、可写控制。我们对比下面两段代码,分析一下两者区别。

代码段一:

// 访问类型实现类
class AccessLevels 
{
public: 
     // 获得只读属性接口
	int getReadOnlay() const {return readOnly;}
	// 设置读写属性接口
	void setReadWrite(int value){readWrite = value;} 
	// 获得读写属性接口
	int getReadWrite()const {return readWrite;} 
	// 设置只写属性接口
	void setWriteOnly(int value){writeOnly = value;} 
private: 
	int noAccess; 
	int readOnly;
	int readWrite; 
	int writeOnly; 
};

代码段二:

class AccessLevels 
{
public:  
	int noAccess; 
	int readOnly;
	int readWrite;
	int writeOnly;
};

代码段一:通过函数接口实现数据的读和写,我们可以方便的实现只读访问和读写访问。这样实现可以很好的体现设计的设计意图。而且也保护了数据成员。

代码段二:将所有数据成员的访问权限均为public。这种实现,使得任何人都可以对class进行操作。但有时并不是设计人员所期望的。假设我们对AccessLevels中noAccess数据成员进行操作。例如:

AccessLevels  access;
Access. noAccess = 10;

如果由于需求的变化导致noAccess数据成员不在需要了。这样会导致程序中所有使用noAccess数据成员的地方都需要进行修改。如果你的程序代码量超过了百万行代码,这种修改将是致命的。

2.增加封装性,为后续实现提供弹性

如果通过函数访问数据成员,后续就可以修改这个函数的实现。而作为客户的使用者却并不知道class内部发生了什么变化。

如下面的测速程序,汽车通过,其速度被计算并填入一个速度收集器内:

class StreamDataCollection 
{
public:
	void   AddValue(int iStream);     //添加一笔新数据 
	double AverageSteam() const;     //返回平均速度
};

考虑AverageSteam。做法之一是在class内设计一个成员变量,记录至今以来所有流量的平均值。当AverageSteam被调用,只返回那个成员变量就好。

另一个做法是令AvrerageSteam每次被调用时,重新计算流量的平均值,此函数有权力调取流量数据收集器内的每一笔流量数据值。

哪一种做法更好,在内存吃紧的机器上,第一种做法会增加StreamDataCollection对象的占用空间,在频繁需要平均值的应用程序中,内存不是重点。

所以,成员变量隐藏在函数接口的背后,可以为“所有可能的实现”提供弹性。例如这可使得成员变量被读或被写时轻松通知其他对象。可以验证class的约束条件及函数的前提和事后状态、可以在多线程环境中执行同步控制……。

除了上述作用外,另外一个优势就是:封装性。如果对客户隐藏成员变量(也就是)封装,保留了日后变更实现的权力。public意味着不封装,不封装意味着不可改变。

特别是被广泛使用的classes而言,因为他们最能够从“改采用一个较佳实现版本”中获益。

3.提供语法的一致性

你成员变量声明为private。如果你想访问这个数据成员,唯一的方法就是接口函数。客户就不用在思考其他的访问方式了。这样即保证了数据访问的唯一性,也防止使用者的纠结,从而节省时间。

按照上面的讨论,如果你使用public这是一种愚蠢的行为,但是如果将数据成员声明为protected呢?protected对数据的包含不彻底,在它的派生类中可访问protected成员变量。因此在一定的范围内它会导致public带来的问题,所以protected不能实现对数据成员的访问控制。同样也存在一致性的问题。因此不能将数据存储成员声明为public的原因也适用于protected。

小心陷阱:在类中将数据成员声明为protected和声明为public两者没有什么区别。两者都会降低类的封装性。

请谨记

  • 将数据成员声明为private,可带来访问数据的一致性,访问控制,并可为以后提供足够的弹性。
  • 将数据声明为protected并不比public更具有封装性。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值