你如何在C ++中创build一个静态类?

你如何在C ++中创build一个静态类? 我应该能够做到这样的事情:

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

假设我创build了BitParser类。 BitParser类定义是什么样的?

如果您正在寻找一种将“static”关键字应用于类的方法,就像您可以在C#中一样,那么您将无法使用Managed C ++。

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

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; } 

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

希望有所帮助! 干杯。

考虑Matt Price的解决scheme 。

  1. 在C ++中,“静态类”没有意义。 最近的事情是只有静态方法和成员的类。
  2. 使用静态方法只会限制你。

你想要的是,用C ++语义来expression,把你的函数(这一个函数)放在一个名字空间中。

编辑2011-11-11

C ++中没有“静态类”。 最接近的概念是只有静态方法的类。 例如:

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

但是你必须记住,“静态类”是类似于Java的语言(例如C#)中的黑客,它们不能具有非成员函数,所以它们只能以静态方法在类中移动它们。

在C ++中,你真正想要的是一个非成员函数,你将在一个名字空间中声明:

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

这是为什么?

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

  • 静态方法可以访问类的私有符号
  • 私有静态方法仍然可见(如果无法访问)给每个人,这违反了一些封装
  • 静态方法不能被转发
  • 静态方法不能被类用户重载而不修改库头
  • 没有什么可以通过一个静态方法来完成,它不可能比同一个命名空间中的一个(可能是朋友)非成员函数
  • 命名空间有它们自己的语义(它们可以组合,可以是匿名的等等)
  • 等等

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

编辑2010-06-10

有一个赞成静态方法的参数,因为有时需要使用静态私有成员variables。

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

“静态私人会员”解决scheme

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

首先,myGlobal被称为myGlobal,因为它仍然是一个全局私有variables。 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 !!! } 

乍看之下,自由functionbarC无法访问Foo :: myGlobal的事实从封装的angular度来看似乎是一件好事情…这很酷,因为看着HPP的人将无法(除非诉诸破坏)访问富:: myGlobal。

但是,如果仔细观察,你会发现这是一个巨大的错误:不仅你的私有variables还必须在HPP中声明(所以对全世界都是可见的,尽pipe是私有的),但是你必须声明在相同的HPP所有(如在所有)function,将被授权访问它!

因此, 使用私人静态会员就像走在裸体的外面,你的爱人在你的皮肤上纹身:没有人有权触摸,但每个人都可以偷看。 而且奖金:每个人都可以拥有被授权与你的私人玩家玩的名字。

private确实…… 😀

“匿名命名空间”解决scheme

匿名命名空间将会使事情变得非常私密。

首先是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。

真的有关系吗?

除非你的代码的用户是破坏者(我会让你,作为一个练习,find一个人如何使用一个肮脏的行为 – 未定义的黑客访问公共类的私人部分…),什么是private ,甚至如果它在头中声明的类的private部分中可见。

不过,如果你需要添加另一个“私人函数”访问私人成员,你仍然必须通过修改标题来向全世界宣布它,这是一个悖论,就我而言: 如果我改变我的代码(CPP部分),那么接口(HPP部分)不应该改变。 引用列奥尼达斯:“ 这是封装!

编辑2014-09-20

何时类静态方法实际上比非成员函数的命名空间更好?

当您需要将function分组在一起并将该组提供给模板时:

 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 !!! 

因为,如果一个类可以是一个模板参数,那么命名空间就不能。

您也可以在名称空间中创build一个自由函数:

在BitParser.h中

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

在BitParser.cpp

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

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

如果您正在寻找将“static”关键字应用于某个类的方法,例如您可以在C#中使用该方法

静态类只是编译器手持你并阻止你写任何实例方法/variables。

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

我可以写static class东西吗?

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

更改:在C ++中,静态或外部说明符只能应用于对象或函数的名称。 在C ++中使用这些指定符与types声明是非法的。 在C中,这些说明符在types声明中被忽略。 例:

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

基本原理:存储类说明符在与types关联时没有任何含义。 在C ++中,可以使用静态存储类说明符声明类成员。 在types声明中允许使用存储类说明符会使用户对代码感到困惑。

struct一样, class也是一个types声明。

附录A中的语法树也可以推导出来。

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

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

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

你应该可以使用BitParser :: getBitAt()来调用函数,而不需要实例化一个我认为是所需结果的对象。

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

在托pipeC ++中,静态类语法是: –

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

… 迟到总比不到好…

这与C ++在C ++中的做法类似

在C#file.cs中,你可以在一个公共函数中拥有私有的variables。 在另一个文件中,您可以通过使用如下函数调用命名空间来使用它:

 MyNamespace.Function(blah); 

以下是如何在C ++中实现相同的function:

SharedModule.h

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

SharedModule.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 } } 

OtherFile.h

 #include "SharedModule.h" 

OtherFile.cpp

 //Call the functions using the hidden variables SharedData::SetError("Hello", "World"); SharedData::DisplayError(); 

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