隐藏'静态'类变量

时间:2011-02-12 08:41:54

标签: c++ static-members static-functions

所以我最近发现了一些使用特定技术的源代码(成语?)我以前没见过;简而言之;而不是使用相关类的静态变量,它在类源文件中使用了一个局部变量。

myclass.h

class myclass {
    //static int myint;

public:
    myclass();
    ~myclass();
    int count();
};

myclass.cpp

#include "myclass.h"

int myint = 0;

myclass::myclass() {
    myint++;
}
myclass::~myclass() {
    myint--;
}

int myclass::count() {
    return myint;
}

的main.cpp

#include "myclass.h"
#include <iostream>

int main() {
    myclass aclass;
    myclass theclass;

    std::cout << theclass.count(); //outputs 2
    return 0;
}

我的问题是,为什么有人会采用这种方法而不是使用静态变量?

我对它的看法是,理想情况下,变量只能为myclass类(私有静态)所知,并且继承根本不重要(在这种情况下),这可能会阻止其他人知道这个变量。但这是我能看到的唯一优势;不确定这是否值得保证。

同样的问题适用于私有的(静态/非静态)成员函数;当继承不重要时。

编辑:在阅读完之后,我会说是因为有些人仍然使用C编程风格......

3 个答案:

答案 0 :(得分:7)

使用静态成员变量或全局变量或本地声明的静态变量并不重要;唯一重要的是对象必须具有静态存储持续时间。除此之外,选择主要基于个人偏好或编码风格指南。

不幸的是,这段代码基本上是错误的。虽然myint是“隐藏的”并且只能从myclass.cpp中直接访问,但它仍然具有外部链接。这意味着可以从其他翻译单元访问它(在其他翻译单元中使用extern int myint),其定义可能与其他翻译单元中myint的其他定义冲突。

为了纠正这个问题,它应该被声明为static(给它内部链接),或者最好,它应该在未命名的命名空间中声明,

namespace {
    int myint;
}

(未命名的命名空间中的对象可能仍然具有外部链接,但它具有唯一的名称,因此不能通过其名称从编译它的转换单元之外使用它。)

答案 1 :(得分:3)

在您的示例中,变量不是静态的,如果正确声明,则在编译单元外部在技术上可见。如果这不是故意的,如果另一个编译单元对具有相同名称的变量使用相同的技巧,则可能是问题的根源(为了解决这个问题,请参阅James McNellis的回答)。

假设正确声明了静态(例如,使用未命名的命名空间方法),这种技术可能比静态类更好,因为它完全隐藏了类用户的变量。这意味着如果您需要添加或修改该变量,则甚至不需要重新编译客户端(您只需要重新编译实现.cpp文件然后重新链接程序)。如果你的类在一个大项目中的任何地方都被使用(由于内部细节发生变化,只编译一个文件而不是重新编译整个世界),这可能会有很大的不同。

此外,如果静态变量不是int但更复杂的东西(例如模板化的类实例),那么将变量作为静态放入类中需要向客户端公开更多的数据,从而引入不需要的依赖项

有时,这个不受欢迎的依赖问题被认为非常重要,您可以找到“compiler firewall”习惯用法的实现。这种隐藏是它的部分和轻量级版本。

答案 2 :(得分:1)

  

我的问题是,为什么有人会采用这种方法而不是使用静态变量?

如果你有东西可以隐藏它是有意义的 - 一个int通常不值得隐藏,但是一个大型库是。在某些情况下,作者也可能更喜欢隐藏客户端的实现细节。

关于静态函数 - 如果它们只是免费帮助程序,我通常会隐藏它们,并且实际上不属于,或者必须是类接口的一部分。

通常,我会将它放在类界面中,仅用于组织目的。