所以我最近发现了一些使用特定技术的源代码(成语?)我以前没见过;简而言之;而不是使用相关类的静态变量,它在类源文件中使用了一个局部变量。
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编程风格......答案 0 :(得分:7)
使用静态成员变量或全局变量或本地声明的静态变量并不重要;唯一重要的是对象必须具有静态存储持续时间。除此之外,选择主要基于个人偏好或编码风格指南。
不幸的是,这段代码基本上是错误的。虽然myint
是“隐藏的”并且只能从myclass.cpp中直接访问,但它仍然具有外部链接。这意味着可以从其他翻译单元访问它(在其他翻译单元中使用extern int myint
),其定义可能与其他翻译单元中myint
的其他定义冲突。
为了纠正这个问题,它应该被声明为static
(给它内部链接),或者最好,它应该在未命名的命名空间中声明,
namespace {
int myint;
}
(未命名的命名空间中的对象可能仍然具有外部链接,但它具有唯一的名称,因此不能通过其名称从编译它的转换单元之外使用它。)
答案 1 :(得分:3)
在您的示例中,变量不是静态的,如果正确声明,则在编译单元外部在技术上可见。如果这不是故意的,如果另一个编译单元对具有相同名称的变量使用相同的技巧,则可能是问题的根源(为了解决这个问题,请参阅James McNellis的回答)。
假设正确声明了静态(例如,使用未命名的命名空间方法),这种技术可能比静态类更好,因为它完全隐藏了类用户的变量。这意味着如果您需要添加或修改该变量,则甚至不需要重新编译客户端(您只需要重新编译实现.cpp文件然后重新链接程序)。如果你的类在一个大项目中的任何地方都被使用(由于内部细节发生变化,只编译一个文件而不是重新编译整个世界),这可能会有很大的不同。
此外,如果静态变量不是int
但更复杂的东西(例如模板化的类实例),那么将变量作为静态放入类中需要向客户端公开更多的数据,从而引入不需要的依赖项
有时,这个不受欢迎的依赖问题被认为非常重要,您可以找到“compiler firewall”习惯用法的实现。这种隐藏是它的部分和轻量级版本。
答案 2 :(得分:1)
我的问题是,为什么有人会采用这种方法而不是使用静态变量?
如果你有东西可以隐藏它是有意义的 - 一个int通常不值得隐藏,但是一个大型库是。在某些情况下,作者也可能更喜欢隐藏客户端的实现细节。
关于静态函数 - 如果它们只是免费帮助程序,我通常会隐藏它们,并且实际上不属于,或者必须是类接口的一部分。
通常,我会将它放在类界面中,仅用于组织目的。