Get/Set函数和public成员变量

来源:互联网 发布:比特币源码 编辑:程序博客网 时间:2024/04/26 11:46

Get/Set函数和public成员变量

在我们设计类的时候,对于类的数据成员,我们可以有三种方法来让类外的函数或者其他类来访问,他们分别是:

  1. 把它设置成public数据成员
  2. 把要访问它的函数或者类设置为当前类的友元
  3. 创建一个set函数来修改该成员数据和一个get函数来读取这个成员。

 三种方法各有优缺点。本文试图根据自己经验对三种方式进行分析。

公共数据成员

下面代码演示了一个公共的数据成员定义和使用的方法。

class CFoo
{
     
public:
             
int x;
}
;

void Bar()
{
     CFoo foo;
     foo.x 
= 1;
     cout 
<< foo.x << endl;
}

这种方法最大的好处是设计简单,你不需要做额外的工作,这个数据成员就可以直接被外部访问。

这种方法的缺点是,你无法控制其它函数或者类对它的访问。这种不可控的方法在一些特殊的情况下会导致问题。假定你设计如下一个圆类:

class CCircle
{
      
public:
                
double m_radius;//半径
                 double area(){return pi*m_radius * m_radius;};
}
;

在设计之初,你对圆类的要求非常低,因此上面的代码没有问题。但是后来在计算过程中,你发现计算面积的过程频繁的被调用,因此你打算在圆类内部记录它的面积,因此修改代码如下:

 

class CCircle
{
public:
    
double m_radius;
   
double m_area;
   
void SetRadius(double r){ m_radius =r; m_area = pi**r;}
}
;

考虑你是一个圆类的用户,你可能写出如下代码:

 

void ReadCircle(CCircle & c)
{
       cout 
>> c.m_radiius;
}

当圆类被修改后,上面这段代码可能会忘记做合理的修改,这样,m_radius被修改了,而m_area没有被修改,这就导致了对象自身的数据错误。这种错误可能花你几个月的时间去找到原因。

2. Get/Set函数

为了解决上面的问题,我们可以考虑修改类定义,提供一对Get/Set函数来访问数据成员。修改的类可能如下:

 

class CCircle{
private:
    
double m_radius;//半径
public:
    
double GetRadius()const{return m_radius;}//注意这里的cost,因为Get函数一般不需要修改对象自身
    void SetRadius(double r) 
    
{
                 m_radius 
= r;
                m_area 
= pi * r * r;
     }
;
    
double GetArea()const{return m_area;};
    CCircle(
double r){SetRadius(r);};
}
;

注意除了Set和Get函数之外,我还增加了一个构造函数。这是因为当你把radius设置为private之后,实际上类外已经无法初始化他,因此需要加一个构造函数来初始化它。

当你想增加功能,统计所有实例中半径最大的圆的半径时,这样的设计就可以凸现出其好处。对于普通的CCircle类的客户而言,你不需要做任何修改。你要修改的只是SetRadius一个函数而已。

这种方法的缺点是你需要做更多的代码工作。当类的成员很多时,这种缺点有时还是很明显的。

友元函数

友元是上述两种方式的折中,通过增加一个友元函数,外部函数或者类可以直接访问所有的成员。这样做的好处是代码量小,你需要维护圆类和一小组访问圆类的函数。但是需要注意的是,你的友元类能访问你的类中的一切,包括有时你不想暴露给其他函数的成员。