代码之家  ›  专栏  ›  技术社区  ›  andrewrk

如何在C++中创建静态类?

  •  230
  • andrewrk  · 技术社区  · 16 年前

    如何在C++中创建静态类?我应该可以做一些像:

    cout << "bit 5 is " << BitParser::getBitAt(buffer, 5) << endl;
    

    假设我创造了 BitParser 班级。会有什么 位元分析器 类定义看起来像?

    12 回复  |  直到 6 年前
        1
  •  244
  •   justderb    8 年前

    如果你正在寻找一种将“静态”关键字应用到类中的方法,比如你可以在C语言中使用,那么你就不可能不使用托管C++。

    但从示例的外观来看,您只需要在BitParser对象上创建一个公共静态方法。像这样:

    BitParser

    class BitParser
    {
     public:
      static bool getBitAt(int buffer, int bitIndex);
    
      // ...lots of great stuff
    
     private:
      // Disallow creating an instance of this object
      BitParser() {}
    };
    

    位PARSPR.CPP

    bool BitParser::getBitAt(int buffer, int bitIndex)
    {
      bool isBitSet = false;
      // .. determine if bit is set
      return isBitSet;
    }
    

    可以使用此代码以与示例代码相同的方式调用方法。

    希望有帮助!干杯。

        2
  •  223
  •   Paul Masri-Stone    6 年前

    考虑 Matt Price's solution .

    1. 在C++中,一个“静态类”没有意义。最接近的是一个只包含静态方法和成员的类。
    2. 使用静态方法只会限制您。

    你想要的是用C++语义表达你的函数 一个函数)。

    编辑2011-111-11

    C++中没有“静态类”。最近的概念将是一个只包含静态方法的类。例如:

    // header
    class MyClass
    {
       public :
          static void myMethod() ;
    } ;
    
    // source
    void MyClass::myMethod()
    {
       // etc.
    }
    

    但是你必须记住,“静态类”是Java类语言(例如C语言)中的黑客,它们无法拥有非成员函数,因此他们将它们作为静态方法移动到类内。

    在C++中,您真正想要的是在命名空间中声明的非成员函数:

    // header
    namespace MyNamespace
    {
       void myMethod() ;
    }
    
    // source
    namespace MyNamespace
    {
       void myMethod()
       {
          // etc.
       }
    }
    

    为什么会这样?

    在C++中,命名空间比“Java静态方法”模式更强大,因为:

    • 静态方法可以访问类的私有符号
    • 私有静态方法仍然对每个人可见(如果无法访问),这在一定程度上破坏了封装
    • 静态方法不能向前声明
    • 在不修改库头的情况下,类用户不能重载静态方法。
    • 在同一个命名空间中,静态方法不能比(可能是友元)非成员函数做得更好。
    • 名称空间有自己的语义(它们可以组合,可以是匿名的,等等)。
    • 等。

    结论:在C++中不要复制/粘贴Java/C模式。在爪哇/ C,模式是强制性的。但是在C++中,它的风格不好。

    编辑2010-06-10

    有一个参数支持静态方法,因为有时需要使用静态私有成员变量。

    我有点不同意,如下所示:

    “静态私有成员”解决方案

    // HPP
    
    class Foo
    {
       public :
          void barA() ;
       private :
          void barB() ;
          static std::string myGlobal ;
    } ;
    

    首先,myglobal被称为myglobal,因为它仍然是全局私有变量。查看CPP来源将澄清:

    // CPP
    std::string Foo::myGlobal ; // You MUST declare it in a CPP
    
    void Foo::barA()
    {
       // I can access Foo::myGlobal
    }
    
    void Foo::barB()
    {
       // I can access Foo::myGlobal, too
    }
    
    void barC()
    {
       // I CAN'T access Foo::myGlobal !!!
    }
    

    乍一看,自由函数barc不能访问foo::myglobal这一事实从封装的角度来看似乎是一件好事…这很酷,因为看HPP的人将无法(除非诉诸破坏)访问foo::myglobal。

    但是如果你仔细观察它,你会发现这是一个巨大的错误:不仅你的私有变量必须在HPP中声明(因此,尽管它是私有的,但对全世界都是可见的),而且你必须在同一个HPP中声明所有被授权访问它的(和所有一样)功能!!!!

    所以 使用一个私人的静态成员就像赤身裸体地走在外面,你的爱人的名单纹在你的皮肤上:没有人被授权触摸,但每个人都可以偷看。还有奖金:每个人都可以有那些被授权与你的私人空间玩耍的人的名字。

    private 的确。。。 -D

    “匿名名称空间”解决方案

    匿名名称空间将具有使事物真正私有化的优势。

    首先,水电站总管

    // HPP
    
    namespace Foo
    {
       void barA() ;
    }
    

    只是要确保你说过:没有无用的芭比宣言,也没有我的全球宣言。这意味着没有人读到标题知道巴拉背后隐藏着什么。

    然后,CPP:

    // CPP
    namespace Foo
    {
       namespace
       {
          std::string myGlobal ;
    
          void Foo::barB()
          {
             // I can access Foo::myGlobal
          }
       }
    
       void barA()
       {
          // I can access myGlobal, too
       }
    }
    
    void barC()
    {
       // I STILL CAN'T access myGlobal !!!
    }
    

    如您所见,像所谓的“静态类”声明一样,fooa和foob仍然能够访问myglobal。但其他人都不行。除了这个CPP没有人知道foob和myglobal的存在!

    不同于“静态类”裸体行走,她的地址簿纹身在她的皮肤上,“匿名”的名称空间是全套衣服。 似乎更好地封装了Afaik。

    这真的很重要吗?

    除非你的代码的用户是破坏者(作为练习,我将让你找出如何使用不确定的黑客行为访问公共类的私有部分…),什么是 私有的 私有的 ,即使它在 私有的 在头中声明的类的节。

    但是,如果您需要添加另一个访问私有成员的“私有函数”,您仍然必须通过修改头向所有人声明它,就我而言,这是一个悖论: 如果我更改了代码的实现(cpp部分),那么接口(hpp部分)不应该更改。 引用列奥尼达的话: 这是封装!

    编辑2014-0920

    什么时候类静态方法实际上比具有非成员函数的命名空间更好?

    当您需要将函数分组并将该分组提供给模板时:

    namespace alpha
    {
       void foo() ;
       void bar() ;
    }
    
    struct Beta
    {
       static void foo() ;
       static void bar() ;
    };
    
    template <typename T>
    struct Gamma
    {
       void foobar()
       {
          T::foo() ;
          T::bar() ;
       }
    };
    
    Gamma<alpha> ga ; // compilation error
    Gamma<Beta> gb ;  // ok
    gb.foobar() ;     // ok !!!
    

    因为,如果类可以是模板参数,则命名空间不能。

        3
  •  59
  •   Matt Price    16 年前

    还可以在命名空间中创建自由函数:

    在BitParser

    namespace BitParser
    {
        bool getBitAt(int buffer, int bitIndex);
    }
    

    在bitparser.cpp中

    namespace BitParser
    {
        bool getBitAt(int buffer, int bitIndex)
        {
            //get the bit :)
        }
    }
    

    一般来说,这是编写代码的首选方法。当不需要对象时,不要使用类。

        4
  •  12
  •   Orion Edwards    16 年前

    如果您正在寻找一种将“static”关键字应用于类的方法,例如,您可以在C中这样做

    静态类只是编译器的一只手,握着你的手,阻止你编写任何实例方法/变量。

    如果你只写一个普通类,没有任何实例方法/变量,那是一样的,这就是你在C++中所做的。

        5
  •  11
  •   Philip Reynolds    16 年前

    在C++中,你要创建一个类的静态函数(不是静态类)。

    class BitParser {
    public:
      ...
      static ... getBitAt(...) {
      }
    };
    

    然后,您应该能够使用bitparser::getbitat()调用函数,而不需要实例化一个我认为是所需结果的对象。

        6
  •  10
  •   Ciro Santilli OurBigBook.com    7 年前

    我能写点什么吗 static class ?

    ,根据 C++11 N3337 standard draft 附录C7.1.1:

    更改:在C++中,静态或外部说明符只能应用于对象或函数的名称。 在C++中使用带有类型声明的说明符是非法的。在C中,使用时忽略这些说明符 在类型声明上。例子:

    static struct S {    // valid C, invalid in C++
      int i;
    };
    

    理由:与类型关联时,存储类说明符没有任何意义。在C++中,类 成员可以用静态存储类说明符声明。允许类型上的存储类说明符 声明可能会让用户混淆代码。

    并且喜欢 struct , class 也是类型声明。

    通过浏览附录A中的语法树,可以得出相同的结论。

    注意到这一点很有趣 static struct 在C中是合法的,但没有效果: Why and when to use static structures in C programming?

        7
  •  5
  •   Netzer    15 年前

    你可以在C++中拥有一个静态类,正如前面提到的,静态类是一个没有任何实例化的对象的类。在C++中,可以通过将构造函数/析构函数声明为私有来获得。最终结果相同。

        8
  •  4
  •   Malc B    14 年前

    在托管C++中,静态类语法是:

    public ref class BitParser abstract sealed
    {
        public:
            static bool GetBitAt(...)
            {
                ...
            }
    }
    

    …迟做总比不做强…

        9
  •  3
  •   sth    14 年前

    这类似于C++在C++中的实现方式。

    在c file.cs中,在公共函数中可以有私有var。 当在另一个文件中时,您可以通过调用具有以下函数的命名空间来使用它:

    MyNamespace.Function(blah);
    

    下面是如何在C++中实现同样的功能:

    SharedModule

    class TheDataToBeHidden
    {
      public:
        static int _var1;
        static int _var2;
    };
    
    namespace SharedData
    {
      void SetError(const char *Message, const char *Title);
      void DisplayError(void);
    }
    

    共享模块.cpp

    //Init the data (Link error if not done)
    int TheDataToBeHidden::_var1 = 0;
    int TheDataToBeHidden::_var2 = 0;
    
    
    //Implement the namespace
    namespace SharedData
    {
      void SetError(const char *Message, const char *Title)
      {
        //blah using TheDataToBeHidden::_var1, etc
      }
    
      void DisplayError(void)
      {
        //blah
      }
    }
    

    其他文件

    #include "SharedModule.h"
    

    其他文件

    //Call the functions using the hidden variables
    SharedData::SetError("Hello", "World");
    SharedData::DisplayError();
    
        10
  •  3
  •   Bharath Ravindra    11 年前

    与其他托管编程语言不同,“静态类”在C++中没有任何意义。您可以使用静态成员函数。

        11
  •  2
  •   Mikhail Vasilyev    6 年前

    正如这里已经注意到的,在C++中实现这一点的一个更好的方法可能是使用命名空间。但由于没有人提到 final 关键字在这里,我张贴什么直接等效 static class 从C++中看起来像C++ 11或更高版本:

    class BitParser final
    {
    public:
      BitParser() = delete;
    
      static bool GetBitAt(int buffer, int pos);
    };
    
    bool BitParser::GetBitAt(int buffer, int pos)
    {
      // your code
    }
    
        12
  •  0
  •   Josh Olson    6 年前

    当使用这些类实现继承上的组合时,名称空间对于实现“静态类”可能不太有用。命名空间不能是类的朋友,因此不能访问类的私有成员。

    class Class {
     public:
      void foo() { Static::bar(*this); }    
    
     private:
      int member{0};
      friend class Static;
    };    
    
    class Static {
     public:
      template <typename T>
      static void bar(T& t) {
        t.member = 1;
      }
    };