c ++私有静态成员变量与免费非成员相比

时间:2015-02-16 10:24:24

标签: c++ private member


我对C ++很陌生,对私有静态成员或“免费非常规”有疑问。

我可以像这样编写代码:

// MyClass.h - Version 1
class MyClass
{
public:
    MyClass();
    ~MyClass();
private:
    static int iValue;
};

// MyClass.cpp
int MyClass::iValue = 123;

没有私有成员的另一种方式,在cpp内部有内部链接

// Version 2 - static 
static int iValue = 123;

// or anonymouse namespace
namespace
{
    int iValue2 = 123;
}

我能看到的唯一区别是来自课外的“可见性”,即使我不能使用它。
如果我想在外部或派生类中使用iValue,我会声明版本1中的静态成员是公共的,或者在类中保护或者完全全局。 使用关键字 const 对我来说更加不清楚。

class MyClass
{
private:
    static const int iValue;
// (...)
}

我总是希望从外面隐藏尽可能多的东西。

简而言之:我有什么理由选择版本1到版本2吗?

亲切的问候 妮斯

3 个答案:

答案 0 :(得分:0)

封装是面向对象编程的主要范例之一,因此如果静态成员仅由类本身使用(例如,计算类对象的数量),则应使用版本1(私有静态成员)。当然,如果您希望派生类能够使用它,您应该将其设置为protected

如果变量未特别绑定到任何类,则应使用版本2/3(静态全局变量),并且可以在不同的位置使用。但是,人们可能会争辩说需要全局变量的代码设计得很糟糕,使用全局变量被认为是一种糟糕的风格。

如果您需要某个特定类的常量值(例如汽车的车轮数),可以使用私有静态const成员。

答案 1 :(得分:0)

MyClass(类,而不是实例)是否有iValue

是=>使它成为一个静态成员。

否=>做点什么。

你想知道该怎么做,这表明你现在没有明显的权衡。 这是一个很好的指标,你可以而且应该做正确的事情©,这使得其他人能够尽可能简单地理解你的代码,这反过来意味着:专注于代码的语义。

Do Do Right Thing人的另一点:关注点的分离,你的班级应该只做一件事,一件事。如果iValue在课堂上没有任何关系,但是你希望它能在某个类别的某个地方进行:不要把它当作吉米。

答案 2 :(得分:0)

这个领域的设计决策需要平衡一些事情,这些事情很容易理解,所以每次需要这样的选择时你都可以权衡利弊:

  • 匿名命名空间或静态非成员允许所有以后代码翻译单元完全访问。

    • 在实现文件中使用(例如“.cc”/“。cpp”),它们会让您拥有一些静态数据/函数 - 而不是对象符号表中的extern - 它们不能可以通过其他翻译单位的代码访问。

      • 较小的符号表有时可以减少程序链接和/或加载时间。

      • 这通常被视为具有较少的封装私有成员变量,因为多个类的代码和朋友可以访问/更改数据(但是类成员的定义可能会传播在许多翻译单元中,私有数据更容易受到某些类型的“黑客”访问,例如客户端提供的模板专业化 - 没有什么是彻底清理的。)

        • 如果您希望翻译单元中的更多代码可以访问,则需要更少的封装:您正在寻找“非常适合”实际需求。
      • 这减少了(重新)编译依赖(在Lakosian术语中称为“物理依赖”),这意味着您可以在不编辑标题的情况下更改数据/函数,只需重新编译转换单元即可获取新数据/行为被链接以通过许多客户端对象/可执行文件进行合并;与编辑头文件相反,后者往往需要重新编译并重新链接所有客户端代码以便合并。在企业级开发中,这可能是低级库更改的一个大问题。

    • 它们很少很少在标题中使用,因为包含这样一个标题的每个翻译单元都会得到数据/函数的独立“副本”,而且它很少见。程序,希望每个翻译单元存储状态;这通常不会干净地映射到程序数据中的逻辑上有意义的分区(例如,每个线程,运行时每个“用户”),即使程序可以结构化,因此看起来很有用,通常使用管理多个数据副本更好对象实例,使其与翻译单元脱钩,以保留后续源代码重构/重组的灵活性。

    • 他们无法访问任何类的私有/受保护成员,并且有人建议他们可能与任何特定类无关并且可能是可重用的,这取决于它的真实性 - 可以帮助或阻碍开发人员的理解在分析数据使用或功能行为/实施时。