2011-02-12 112 views
2

所以我最近发现它使用了特别的技术我从来没有见过的一些源代码(成语);简而言之;而不是为有问题的类使用静态变量,它使用类源文件中的局部变量。隐藏“静态”类变量

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类(private static)知道,并且继承并不重要(在这种情况下),这可能会阻止其他人知道这个变量。但那是我能看到的唯一优势;不知道这是否值得。

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

编辑:阅读后左右,我打算做一个刺,这是因为有些人还在用C编程风格...

回答

7

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

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

为了纠正这一点,应该要么被声明static(给它的内部连接),或者优选地,它应该在不具名命名空间声明,

namespace { 
    int myint; 
} 

(一个在未命名的命名空间对象可能仍然有外部链接,但它是唯一命名的,所以它不能在编译它的转换单元外使用它的名称。)

+0

+1使用无名命名空间,作为[静态]的[高级替代](http://stackoverflow.com/questions/4422507/superiority-of-unnamed-namespace-over-static)。 – Nawaz 2011-02-12 08:48:03

+3

值得一提的是,大多数在线C++教程在技术上不正确,或者提倡穷人的风格。 (真的很伤心,真的......) – 2011-02-12 08:50:58

3

在您的示例中,该变量不是静态的,并且在编译单元外部在技术上是可见的if正确申报。如果这不是有意的,那么如果另一个编译单元对具有相同名称的变量使用相同的技巧(要解决此问题,请参阅James McNellis的答案),可能会产生问题。

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

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

有时,这种不需要的依赖性问题被认为非常重要,您可以找到“compiler firewall”成语的实现。这种隐藏是它的一个部分和简单的版本。

1

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

它是有道理的,如果你有东西隐藏 - 一个int不值得通常隐藏,但一个大型图书馆是。在某些情况下,作者可能也倾向于隐藏客户的实现细节。

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

一般来说,我只是为了组织目的将它放在类接口中。