我对C ++中的全局变量有疑问。我来自Java背景,您可以在其中声明和使用实例变量,如下所示:
Example.java
class Example
{
int x;
doSomththing()
{
x = 1;
}
doSomethingElse()
{
x = 2;
}
}
我的问题是,在C ++中,如果我做类似的事情,它会被归类为全局变量或实例变量。观察我的C ++示例以澄清:
example.h文件
class Example{
public:
void do_something();
void do_somethingElse();
private:
int x;
};
Example.cpp
#include Example.h
void Example::do_something()
{
x = 1;
}
void Example::do_somethingElse()
{
x = 2;
}
那么在C ++示例中,x是全局变量还是实例变量?如果它不是全局的,那么如何将x正确定义为全局?
答案 0 :(得分:3)
如果创建Example的新实例,则x不相同,它是一个实例变量。如果希望在Example的所有实例之间共享x,则应将其定义为static
答案 1 :(得分:1)
就像在Java或C#中一样,x也是一个实例变量。无论好坏,C ++允许在类定义之外的变量,如下所示:
class Example{
public:
void do_something();
void do_somethingElse();
private:
int x;
};
Example.cpp
#include Example.h
static int g_value = 17;
extern int g_another_value;
void Example::do_something()
{
x = g_value + g_another_value + 1;
}
void Example::do_somethingElse()
{
x = g_value - g_another_value + 2;
}
OtherCode.cpp
int g_another_value = 31;
// other code
在这种情况下, static 关键字将允许范围仅包含此文件,但是删除静态,并在其他cpp文件中重新声明该变量,前面是关键字 extern 将允许编译器满意,链接器将解析变量。
希望这有帮助。
答案 2 :(得分:1)
全局变量在C / C ++中声明,只需将它放在任何类语句之外的顶层,这是Java中无法实现的。
int y;
示例中的变量x
显然是一个实例变量。除了可见性(私有与包)之外,它与Java示例中的x
完全等效。
答案 3 :(得分:0)
首先,您应该知道您的Java示例无法1:1转换为C ++,因为C ++不知道 package-private accessibility (事实上,C ++实际上没有包在语言层面,并且将它们添加到语言中的提议没有进入C ++ 11)。您的类Example
及其x
字段和方法都是包私有的,这意味着它们对包外的任何代码都是隐藏的。
C ++只知道public
,protected
和private
,它们大部分(但不完全!)对应于它们的Java等价物,但它也知道朋友函数和类,有时可用于实现类似于包私有可访问性的结果。
除了这个可访问性问题之外,C ++示例中的x
变量与Java示例中的相同,即它是一个实例变量,在每个类的实例中都有单独的值。
在C ++中可以使用全局变量,但正如您可能已经知道的那样,它们通常是糟糕的设计。想象一下这个完整的C ++程序:
int x; // global variable, usually bad
int main()
{
x = 123;
}
这是否意味着Java会阻止这种糟糕的设计?不,不是的。它使您免受C ++中全局变量带来的一些令人惊讶的危险低级方面的影响(详情请参阅static initialization order fiasco),但不是来自糟糕的高级方面。 公共静态变量非最终非常类似于C ++中的普通全局变量。
获取此Java代码,例如:
public class Example {
public static int x; // hardly better than a global variable in C++
}
这几乎不比C ++中的“真实”全局变量好。整个程序中的每一段代码都可以访问它,这会增加紧耦合并影响可测试性。
这是Java中伪装的坏全局变量的另一个例子:
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private int x; // global variable in disguise
private Singleton() {
}
public static Singleton getInstance() {
return INSTANCE;
}
public int getX() {
return x;
}
public void setX(int newX) {
x = newX;
}
}
(是的,Singleton设计模式 只不过是我在任何一段代码中见过的所有案例中99%的美化全局变量。)
关键是:从技术上讲,Java不具有像C ++这样的全局变量,但是模拟它们的行为和缺陷并不难,然后它们就完全一样糟糕(减去C ++中存在的一些低级初始化问题)。他们只是看起来更好,更清洁“周围的所有课程,特别是初学者。
顺便说一下,你也可以在C ++中实现Singleton(反)模式,它通常也不仅仅是一个美化的全局变量:
class Singleton
{
private:
static Singleton *instance;
int x; // global variable in disguise
Singleton() : x(0) {}
public:
static Singleton &instance()
{
// ignoring any concurrency issues for
// simplicity's sake, don't try this at
// home
if (instance == nullptr)
{
instance = new Singleton;
}
return *instance;
}
void setX(int newX) { x = newX; }
int getX() const { return x; }
};
您也可以使用static
,public
和非const
的组合伪装创建更简单的全局变量,就像在Java中一样:
class Example
{
public:
static int x; // global variable in disguise
};
只是为了说明这一点: static
并非邪恶。但你必须知道在哪里应用它,你必须意识到public
的组合,static
和非final
/非 - const
通常是用于“真正的”全局变量(在Java中以及在C ++中)的一种(良好的,但短视的)替代品