如何在C ++中创建静态类?
如何在C ++中创建静态类?我应该能够做类似的事情:
cout << "bit 5 is " << BitParser::getBitAt(buffer, 5) << endl;
假设我创建了BitParser
类。 BitParser类定义会是什么样?
解决方案
回答
在C ++中,我们想创建一个类的静态函数(而不是静态类)。
class BitParser { public: ... static ... getBitAt(...) { } };
然后,我们应该能够使用BitParser :: getBitAt()调用该函数,而无需实例化一个我认为是所需结果的对象。
回答
如果我们正在寻找一种将" static"关键字应用于类的方式(例如在Cfor中),那么如果不使用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; }
我们可以使用此代码以与示例代码相同的方式调用方法。
希望对我们有所帮助!干杯。
回答
If you're looking for a way of applying the "static" keyword to a class, like you can in C# for example
静态类只是编译器,它会牵着手,阻止我们编写任何实例方法/变量。
如果我们只是编写一个没有任何实例方法/变量的普通类,那是同一回事,这就是我们在C ++中要做的
回答
我们还可以在名称空间中创建自由函数:
在BitParser.h中
namespace BitParser { bool getBitAt(int buffer, int bitIndex); }
在BitParser.cpp中
namespace BitParser { bool getBitAt(int buffer, int bitIndex) { //get the bit :) } }
通常,这是编写代码的首选方式。当不需要对象时,不要使用类。
回答
考虑马特·普赖斯(Matt Price)的解决方案。
- 在C ++中,"静态类"没有任何意义。最接近的是只有静态方法和成员的类。
- 使用静态方法只会限制我们。
我们想要的是用C ++语义表示的,将函数(因为它是一个函数)放在名称空间中。
编辑2011-11-11
C ++中没有"静态类"。最接近的概念是只有静态方法的类。例如:
// header class MyClass { public : static void myMethod() ; } ; // source void MyClass::myMethod() { // etc. }
但我们必须记住,"静态类"是类Java语言(例如C#)中的hack,它们无法具有非成员函数,因此它们不得不将其作为静态方法移入类中。
在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的人将无法访问(除非进行破坏活动) Foo :: myGlobal。
但是,如果仔细观察,我们会发现这是一个巨大的错误:不仅必须在HPP中声明私有变量(因此,尽管是私有的,但对全世界都是可见的),而且我们还必须声明在同一HPP中(将在ALL中)所有将被授权访问它的功能!!!
因此,使用私人静态成员就像裸照在外面走动,在皮肤上刺穿了恋人名单:没有人可以触摸,但每个人都可以窥视。好处是:每个人都可以拥有被授权与私人玩耍的人的名字。
确实是"私有" ...
:-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。
真的有关系吗?
除非代码的用户是破坏者(作为练习,我让我们找到如何使用肮脏的行为未定义的hack访问公共类的私有部分的方法……),否则" private"是`私有",即使它在标头中声明的类的"私有"部分中可见。
不过,如果我们需要添加另一个可以访问私有成员的"私有函数",则仍然必须通过修改标头向全世界进行声明,就我而言,这是一个悖论:如果我更改了实现,我的代码(CPP部分),则界面(HPP部分)不应更改。引用莱昂尼达斯的话:"这就是包囊!"
编辑2014-09-20
什么时候类静态方法实际上比具有非成员函数的名称空间更好?
当我们需要将功能分组在一起并将该分组输入模板时:
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 !!!
因为,如果类可以作为模板参数,则名称空间就不能。
回答
如前所述,我们可以在C ++中拥有一个静态类,静态类是一个没有实例化它的对象的类。在C ++中,这可以通过将构造函数/析构函数声明为私有来获得。最终结果是相同的。
回答
这类似于C#在C ++中的实现方式
在Cfile.cs中,我们可以在public函数中包含private var。
在另一个文件中时,可以通过使用以下函数调用名称空间来使用它:
MyNamespace.Function(blah);
这是在C ++中实现相同效果的方法:
共享模块
class TheDataToBeHidden { public: static int _var1; static int _var2; }; namespace SharedData { void SetError(const char *Message, const char *Title); void DisplayError(void); }
共享模块
//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();
回答
在托管C ++中,静态类语法为:-
public ref class BitParser abstract sealed { public: static bool GetBitAt(...) { ... } }
... 迟到总比不到好...