你如何在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 。
- 在C ++中,“静态类”没有意义。 最近的事情是只有静态方法和成员的类。
- 使用静态方法只会限制你。
你想要的是,用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 ++中没有意义。 你可以使用静态成员函数。