C ++全局变量与Java实例变量

时间:2014-04-25 14:23:31

标签: java c++ oop

我对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正确定义为全局?

4 个答案:

答案 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 ++只知道publicprotectedprivate,它们大部分(但不完全!)对应于它们的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; }
};

您也可以使用staticpublic和非const的组合伪装创建更简单的全局变量,就像在Java中一样:

class Example
{
public:
    static int x; // global variable in disguise
};

只是为了说明这一点: static并非邪恶。但你必须知道在哪里应用它,你必须意识到public的组合,static和非final /非 - const通常是用于“真正的”全局变量(在Java中以及在C ++中)的一种(良好的,但短视的)替代品