我应该使用公共或私人变量吗?

时间:2013-01-18 13:26:45

标签: c++ oop abstraction getter-setter data-access

我是第一次做大项目。我有很多类,其中一些有公共变量,一些有setter和getter方法的私有变量,同样有两种类型。

我决定重写此代码,主要只使用一种类型。但我不知道应该使用哪个(仅用于同一对象中的方法的变量始终是私有的,不受此问题的影响)。

我知道公共和私人意味着什么,但在现实世界中使用什么以及为什么?

7 个答案:

答案 0 :(得分:33)

private数据成员通常被认为是好的,因为它们提供了封装。

为他们提供getter和setter打破了封装,但它仍然比public数据成员更好,因为只有一次访问该数据的访问点。

你会在调试过程中注意到这一点。如果它是私有的,你知道你只能修改类中的变量。如果它是公开的,您将必须在整个代码库中搜索可能被修改的位置。

尽可能禁止getter / setter并制作属性private。这遵循信息隐藏的原则 - 您不应该关心类具有什么属性。它应该是独立的。当然,在实践中这是不可行的,如果是这样的话,那么遵循这一设计的设计将比没有设计的设计更加混乱和难以维护。

这当然是一个经验法则 - 例如,我只使用struct(相当于class具有公共访问权限),例如,一个简单的点类:

struct Point2D
{
   double x;
   double y;
};

答案 1 :(得分:16)

既然你说你知道这个理论,并且其他答案已经挖掘了公共/私人,吸气者和制定者的意义,我想集中讨论使用访问者而不是创建公共属性的原因(成员数据)在C ++)。

想象一下,你在后勤项目中有一个类卡车:

class Truck {
public:
    double capacity;

    // lots of more things...
};

如果您是北美人,您可能会使用加仑来代表卡车的容量。想象一下,您的项目已经完成,它完美运行,但Truck::capacity的许多直接用途都已完成。实际上,您的项目取得了成功,因此一些欧洲公司要求您调整您的项目;不幸的是,该项目现在应该使用公制系统,因此应该使用升而不是加仑。

现在,这可能是一团糟。当然,一种可能性是仅为北美准备代码库,而仅为欧洲准备代码库。但这意味着错误修复应该应用于两个不同的代码源,并且这决定是不可行的。

解决方案是在项目中创建配置可能性。用户应该能够设置加仑或升,而不是固定的,硬连线的加仑选择。

通过上面所述的方法,这将意味着很多工作,您将不得不追踪Truck::capacity的所有用途,并决定如何处理它们。这可能意味着修改整个代码库中的文件。作为替代方案,我们假设你决定采用更多的theoretic方法。

class Truck {
public:
    double getCapacity() const
        { return capacity; }

    // lots of more things...
private:
    double capacity;
};

可能的替代更改不涉及对类的接口的修改:

class Truck {
public:
    double getCapacity() const
        { if ( Configuration::Measure == Gallons ) {
            return capacity;
          } else {
             return ( capacity * 3.78 );
          }
        }


    // lots of more things...
private:
    double capacity;
};

(请注意,有很多方法可以做到这一点,只有一种可能性,这只是一个例子)

您必须创建全局实用程序类配置(但您必须执行此操作),并在truck.h中为configuration.h添加包含,但这些都是本地更改,其余您的代码库保持不变,从而避免潜在的错误。

最后,你还说你现在正在一个大项目中工作,我认为这是一个实际上更有意义的领域。请记住,在大型项目中工作时要记住的目标是创建可维护的代码,即可以使用新功能进行更正和扩展的代码。你可以忘记个人小项目中的getter和setter,尽管我会让自己习惯他们。

希望这有帮助。

答案 2 :(得分:5)

对于私人/公共或受保护的内容,没有严格的规定。

这取决于你班级的作用及其提供的内容。

  • 构成内部运作的所有方法和成员 该课程应该是私人
  • 课程提供给外界的一切都应该公开
  • 可能必须在此类的专业化中扩展的成员和方法, 可以声明为受保护

答案 3 :(得分:3)

从OOP的角度来看,getters / setters有助于封装,因此应始终使用。当你调用getter / setter时,类可以在幕后做任何想做的事情,并且类的内部不会暴露在外面。

另一方面,从C ++的角度来看,当你想要获取/设置一个值时,如果类会做很多意想不到的事情,那么它也会是一个缺点。人们喜欢知道某些访问是否会导致巨大的开销或简单而有效。当您访问公共变量时,您确切知道自己得到了什么,当您使用getter / setter时,您根本不知道。

特别是如果你只做一个小项目,花时间编写getter / setter并相应地调整它们,当你决定改变你的变量名称/类型/ ...时会产生大量的繁忙工作而收效甚微。你最好花时间编写一些有用的代码。

C ++代码在不提供实际收益时通常不使用getter / setter。如果你设计一个1,000,000行的项目,其中包含许多必须尽可能独立的模块,那么它可能是有意义的,但是对于大多数正常大小的代码,你每天都在编写它们是有点过分的。

答案 4 :(得分:2)

有些数据类型的唯一目的是保存指定数据的数据。这些通常可以写为具有公共数据成员的结构。除此之外,一个类应该定义一个抽象。公共变量或琐碎的setter和getter表明设计没有被充分考虑,导致弱抽象的聚集,这些抽象不抽象任何东西。考虑行为,而不考虑数据:此类应该执行X,Y和Z.从那里,确定需要哪些内部数据来支持所需的行为。这一开始并不容易,但要不断提醒自己重要的是行为,而不是数据。

答案 5 :(得分:1)

私有成员变量优先于公共成员变量,主要是出于上述原因(封装,明确指定的数据等)。它们还提供了一些数据保护,因为它保证了在没有通过设置器的适当通道的情况下,如果需要,任何外部实体都不能改变成员变量。

getter和setter的另一个好处是,如果您使用的是IDE(如Eclipse或Netbeans),您可以使用IDE的功能在代码库中搜索函数所在的每个位置。它们提供了关于使用或修改该特定类中的数据的可见性的可见性。此外,通过使用内部互斥锁,您可以轻松地访问成员变量线程安全。 getter / setter函数会在访问或修改变量之前获取此互斥锁。

我是抽象的支持者,它仍然有用。为抽象而抽象通常会导致混乱,比其价值更复杂。

答案 6 :(得分:0)

通常不鼓励使用公共变量,更好的形式是将所有变量设为私有并使用getter和setter访问它们:

private int var;

public int getVar() {
  return var;
}

public void setVar(int _var) {
  var = _var;
}
像Eclipse和其他现代IDE一样,通过提供诸如“实现Getters和Setters”和“Encapsulate Field”(用相应的getter和setter调用替换所有变量的直接访问)等功能来帮助您实现这一目标。