3

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

我的班级.h

class myclass {
    //static int myint;

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

我的类.cpp

#include "myclass.h"

int myint = 0;

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

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

主文件

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

int main() {
    myclass aclass;
    myclass theclass;

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

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

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

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

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

4

3 回答 3

7

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

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

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

namespace {
    int myint;
}

(未命名命名空间中的对象可能仍具有外部链接,但它是唯一命名的,因此不能在编译它的翻译单元之外以其名称使用它。)

于 2011-02-12T08:45:41.497 回答
3

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

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

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

有时这种不需要的依赖问题被认为非常重要,以至于您可以找到“编译器防火墙”习语的实现。这种隐藏是它的部分和轻量级版本。

于 2011-02-12T09:05:25.707 回答
1

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

如果你有一些东西要隐藏,这是有道理的——通常不值得隐藏一个 int,但一个大型库是。在某些情况下,作者也可能更愿意对客户隐藏实现细节。

关于静态函数——如果它们只是免费的助手,并且真的不属于或需要成为类接口的一部分,我通常会隐藏它们。

通常,出于组织目的,我会将其放在类接口中。

于 2011-02-12T09:05:46.963 回答