【问题标题】:A global static class to contain data包含数据的全局静态类
【发布时间】:2012-08-17 02:44:32
【问题描述】:

我想要一个静态类来保存不同类型的数据(如目录、值等)。我试过使用namespaces 但namespaces 不允许成员变量,我需要保存数据(如果我错了,请纠正我)。

我要做的是保存一些常量供整个程序使用 - scalingFactorscreenSize 仅举几例。然后,我希望程序的所有部分共享这些数据。像这样的:

在 Foo.cpp 中:

void doSomething( float p_Float ) {
   printf( "Scaled Float is %.2f", p_Float * Globals.scalingFactor );
}

在 Goo.cpp 中:

void doSomethingElse( ) {
   printf( "Scaling Factor is %.2f", Globals.scalingFactor );
}

scalingFactor应该引用同一个值,就是全局静态类GlobalsscalingFactor的值。

提前致谢。

编辑:我还需要使用全局函数,它和这个问题中的变量一样吗?

【问题讨论】:

    标签: c++ oop class


    【解决方案1】:

    因此,只需将其作为static 成员:

    //Globals.h
    class Globals
    { 
    public:
       static float scalingFactor;
    }
    

    在单个实现文件中初始化它:

    //Globals.cpp
    #include "Globals.h"
    float Globals::scalingFactor = 42.0;
    

    并使用作用域解析操作符来访问它:

    float x = Globals::scalingFactor;
    

    我尝试过使用命名空间,但命名空间不允许成员变量

    您没有正确使用命名空间。以下应该有效:

    标题中的声明:

    namespace Globals
    {
        extern float scalingFactor;
    }
    

    以及定义:

    //Globals.cpp
    namespace Globals
    {
        float scalingFactor = 42.0;
    }
    

    【讨论】:

    • 这样,每当我需要使用 Globals 类时,我是否必须创建一个实例? (几分钟前正在阅读静态变量)
    • @LanceGray 没有。您不需要实例。这就是静态成员的工作方式。
    • 谢谢。让我试试看它是否合适。我在命名空间中使用了static 而不是extern,所以这可能就是它不起作用的原因。
    • @LanceGray 在类类型之外使用时,static 给出一个变量internal linkeage。这意味着为每个使用它的翻译单元创建一个副本,因此它不是全局的。
    • @LanceGray 好吧...参考意味着别的东西(查一下)。 extern 声明变量,还没有定义它(你在cpp文件中定义它)。
    【解决方案2】:

    C++ 没有静态类。只是上课。但这听起来像是命名空间的完美工作。是的,您可以将数据放在命名空间中。在头文件中编写声明,数据为 extern;

    // program_data.h:
    namespace program_data {
    extern float scalingFactor;
    extern int screenSize;
    } // namespace program_data
    

    在一个源文件中,为共享数据提供定义:

    // program_data.cpp:
    #include "program_data.h"
    namespace program_data {
    float scalingFactor = 13.765; // whatever...
    int screenSize = 640;
    } // namespace program_data
    

    无论您需要在哪里使用这些东西,只需使用它们的命名空间限定名称来引用它们:

    // foo.cpp:
    #include "program_data.h"
    void doSomething( float p_Float ) {
       printf( "Scaled Float is %.2f", p_Float * program_data::scalingFactor );
    }
    

    而且,是的,严格的 OOP 不会做这种事情。但是将全局数据传递给每个函数,无论它是否需要,都会产生大量开销。这被称为“非法数据”,通常反映了设计错误。如果这些东西真的是全球性的,那么它们就是全球性的,假装它们不是,以使您的代码“OOP”,这是一个设计错误。

    【讨论】:

    • +1 最后 3 句话:太多人提倡跳过箍以一种混淆的方式实现 相同 的事情,只是为了避免被牵连到具有教条式的名声是坏模式。我还要补充一点,C++ 从未伪装成“严格的 OOP”,这是一件的事情。 :)
    【解决方案3】:

    由于您已标记您的问题,我假设您正在设计一个面向对象的系统。如果是这样,我建议不要使用全局变量。考虑为您尝试传递的数据创建有意义的类,然后传递对象而不是访问全局变量。

    例如:

    class Bar {
    private:
      float scalingFactor;
    
    public:
      float getScalingFactor() {
        return scalingFactor;
      }
    }
    
    class Foo {
    private:
      Bar &bar;
    
    public:
      Foo(Bar &bar) : bar(bar) {
      }
    
      void doSomething( float p_Float ) {
        printf( "Scaled Float is %.2f", p_Float * bar.getScalingFactor() );
      }
    }
    
    class Goo {
    private:
      Bar &bar;
    
    public:
      Goo(Bar &bar) : bar(bar) {
      }
    
      void doSomethingElse( ) {
        printf( "Scaling Factor is %.2f", bar.getScalingFactor() );
      }
    }
    

    并且在您创建FooGoo 的地方,您可以将Bar 的相同实例传递给两者:

    Bar bar;
    
    Foo foo(bar);
    foo.doSomething(10);
    
    Goo goo(bar);
    goo.doSomethingElse();
    

    【讨论】:

    • 谢谢,我会记住的。另外,这对我来说似乎更具可读性。但是你能解释一下(或链接到解释)这个语法吗:Foo( Bar &bar) : bar( bar ) { } 它看起来像一个构造函数,但: bar( bar ) 让我感到困惑。
    • @LanceGray:是的,它确实是一个构造函数。 : 之后的部分是初始化成员变量的初始化器。也许这更有意义:Foo(Bar &x) : bar(x)。你可以在这里阅读更多信息:cprogramming.com/tutorial/initialization-lists-c++.html
    • 如果我有一个接受其他参数的构造函数,它是否工作?就像Foo( Bar &x, int i ) : bar( x ) 一样,或者我需要另一个只接受int (Foo( int i )) 的构造函数
    • @LanceGray:是的,您可以拥有任意数量的参数,您可以使用初始化列表或构造函数中的常规赋值或两者的组合来初始化它们。跨度>
    • @Casablanca 当然,在我们可以使用初始化列表的地方,我们应该,因为这是更好的样式并且有时是必不可少的,例如它是初始化一个const 成员变量。
    猜你喜欢
    • 1970-01-01
    • 2022-01-24
    • 2011-03-24
    • 1970-01-01
    • 2011-11-22
    • 2012-03-01
    • 1970-01-01
    • 2021-12-25
    • 1970-01-01
    相关资源
    最近更新 更多