当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何在C++中创建静态类?》经验,为你挑选了7个好方法。

如何在C++中创建静态类?我应该可以这样做:

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

假设我创建了这个BitParser类.将在哪些BitParser类定义是什么样子?



1> OJ...:

如果您正在寻找一种将"static"关键字应用于类的方法,例如您可以在C#中使用,那么您将无法使用Managed C++.

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

BitParser.h

class BitParser
{
 public:
  static bool getBitAt(int buffer, int bitIndex);

  // ...lots of great stuff

 private:
  // Disallow creating an instance of this object
  BitParser() {}
};

BitParser.cpp

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

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

希望有所帮助!干杯.


为了在这种方法中明确您的意图,您还可以使用私有构造函数.`private:BitParser(){}`这将阻止任何人创建实例.
共享状态时@MoatazElmasry线程安全是一个问题.在上面的实现中没有共享的状态,所以线程安全不会有任何问题...除非你愚蠢到使用静态_inside_那些函数.所以,是的,上面的代码是线程安全的,只是保持你的函数的持久状态,你就是好的.
如果是C++ 11,我认为最好用'BitParser()= delete;'来正确地传达删除构造函数的意图(不只是把它隐藏为`private`).
OJ,你有[语法错误](http://cplusplus.syntaxerrors.info/index.php?title=Cannot_declare_member_function_%E2%80%98static_int_Foo::bar()%E2%80%99_to_have_static_linkage).static关键字只应在类定义中使用,而不能在方法定义中使用.

2> paercebal..:

考虑一下Matt Price的解决方案.

    在C++中,"静态类"没有任何意义.最接近的是一个只有静态方法和成员的类.

    使用静态方法只会限制你.

你想要的是,用C++语义表达,将你的函数(因为它一个函数)放在命名空间中.

编辑2011-11-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#的模式.在Java/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将无法(除非采取破坏行为)访问富:: myGlobal.

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

因此,使用私人静态成员就像在裸体外面散步一样,你的爱人纹身在你的皮肤上:没有人有权触摸,但每个人都可以偷看.奖金:每个人都可以拥有被授权与你的私人玩耍的人的名字.

private 确实...... :-D

"匿名命名空间"解决方案

匿名命名空间的优势在于私有化私有.

首先是HPP标头

// HPP

namespace Foo
{
   void barA() ;
}

只是为了确定你说过:barB和myGlobal都没有无用的声明.这意味着没有人阅读标题知道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.

真的有关系吗?

除非你的代码的用户是破坏者(我会让你,作为练习,找到如何使用脏行为 - 未定义的黑客来访问公共类的私有部分......),即使它private是什么private,private在标题中声明的类的部分中可见.

但是,如果你需要添加另一个"私有函数"来访问私有成员,你仍然必须通过修改标题向全世界声明它,就我而言这是一个悖论:如果我改变了实现我的代码(CPP部分),然后界面(HPP部分)不应该改变.引用列奥尼达斯:" 这是封锁! "

编辑2014-09-20

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

当您需要将功能组合在一起并将该组提供给模板时:

namespace alpha
{
   void foo() ;
   void bar() ;
}

struct Beta
{
   static void foo() ;
   static void bar() ;
};

template 
struct Gamma
{
   void foobar()
   {
      T::foo() ;
      T::bar() ;
   }
};

Gamma ga ; // compilation error
Gamma gb ;  // ok
gb.foobar() ;     // ok !!!

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


@Tom:一个跨平台的解决方案是在标题中添加以下代码`#define private public` ... ^ _ ^ ...
GCC支持-fno-access-control,它可以在whitebox单元测试中用于访问其他私有类成员.这就是我能想到的唯一理由来证明在实现中使用类成员而不是匿名/静态全局.

3> Matt Price..:

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

在BitParser.h中

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

在BitParser.cpp中

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

通常,这将是编写代码的首选方法.当不需要对象时不要使用类.


@Torleif:你错了.命名空间比静态私有成员更适合封装.请参阅我的答案进行演示.

4> Orion Edward..:

如果您正在寻找一种将"static"关键字应用于类的方法,例如您可以在C#中使用

静态类只是编译器手持您并阻止您编写任何实例方法/变量.

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



5> Philip Reyno..:

在C++中,您希望创建类的静态函数(而不是静态类).

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

然后,您应该能够使用BitParser :: getBitAt()调用该函数,而无需实例化我认为是所需结果的对象.



6> Ciro Santill..:

我能写点什么static class吗?

,根据C++ 11 N3337标准草案附件C 7.1.1:

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

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

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

而且struct,class也是一种类型声明.

通过走附录A中的语法树可以推导出同样的结果.

有趣的是,它static struct在C 中是合法的,但没有效果:为什么以及何时在C编程中使用静态结构?



7> 小智..:

你可以在C++中拥有一个静态类,如前所述,静态类是没有实例化它的任何对象的类.在C++中,这可以通过将构造函数/析构函数声明为私有来获得.最终结果是一样的.

推荐阅读
殉情放开那只小兔子
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有