如何在C ++中创建静态类?我应该能够做到这样的事情:
cout << "bit 5 is " << BitParser::getBitAt(buffer, 5) << endl;
假设我创建了BitParser
类。 BitParser
类定义是什么样的?
答案 0 :(得分:248)
如果您正在寻找一种将“static”关键字应用于类的方法,例如您可以在C#中使用,那么您将无法使用托管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;
}
您可以使用此代码以与示例代码相同的方式调用方法。
希望有所帮助!欢呼声。
答案 1 :(得分:231)
你想要的是,用C ++语义表达,将你的函数(对于它是一个函数)放在命名空间中。
C ++中没有“静态类”。最近的概念是只有静态方法的类。例如:
// header
class MyClass
{
public :
static void myMethod() ;
} ;
// source
void MyClass::myMethod()
{
// etc.
}
但是你必须记住,“静态类”是类似Java的语言(例如C#)中的黑客,它们不能拥有非成员函数,所以他们反而将它们作为静态方法移动到类中。 / p>
在C ++中,你真正想要的是一个非成员函数,你将在命名空间中声明:
// header
namespace MyNamespace
{
void myMethod() ;
}
// source
namespace MyNamespace
{
void myMethod()
{
// etc.
}
}
在C ++中,命名空间比“Java静态方法”模式的类更强大,因为:
结论:不要在C ++中复制/粘贴Java / C#的模式。在Java / C#中,模式是必需的。但在C ++中,风格很糟糕。
有一个论据支持静态方法,因为有时需要使用静态私有成员变量。
我有点不同意,如下所示:
// 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中)有权访问它的函数!!!
所以使用私人静态成员就像走在外面裸体一样,你的爱人的名单纹在你的皮肤上:没有人有权触摸,但每个人都可以偷看。奖金:每个人都可以拥有被授权与你的私人玩耍的人的名字。
确实......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。
除非你的代码的用户是破坏者(我会让你,作为练习,找到如何使用脏行为 - 未定义的hack来访问公共类的私有部分......),{{ 1}}是private
,即使它在标题中声明的类的private
部分中可见。
但是,如果你需要添加另一个“私有函数”来访问私有成员,你仍然必须通过修改标题向全世界声明它,就我而言这是一个悖论:如果我改变了我的代码(CPP部分)的实现,那么界面(HPP部分)就不应该改变。引用Leonidas:“这是封锁!”
类何时静态方法实际上比具有非成员函数的名称空间更好?
当您需要将功能组合在一起并将该组提供给模板时:
private
因为,如果类可以是模板参数,则命名空间不能。
答案 2 :(得分:60)
您还可以在命名空间中创建自由函数:
在BitParser.h中
namespace BitParser
{
bool getBitAt(int buffer, int bitIndex);
}
在BitParser.cpp中
namespace BitParser
{
bool getBitAt(int buffer, int bitIndex)
{
//get the bit :)
}
}
通常,这是编写代码的首选方法。当不需要对象时,不要使用类。
答案 3 :(得分:12)
如果您正在寻找一种将“static”关键字应用于类的方法,例如您可以在C#中使用
静态类只是编译器手持您并阻止您编写任何实例方法/变量。
如果你只是编写一个没有任何实例方法/变量的普通类,那就是同样的事情,这就是你在C ++中所做的事情
答案 4 :(得分:11)
在C ++中,您想要创建一个类的静态函数(而不是静态类)。
class BitParser {
public:
...
static ... getBitAt(...) {
}
};
然后,您应该能够使用BitParser :: getBitAt()调用该函数,而无需实例化我认为是所需结果的对象。
答案 5 :(得分:10)
我可以写一些类似static class
的内容吗?
否,根据C++11 N3337 standard draft附件C 7.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?
答案 6 :(得分:5)
你可以'在C ++中拥有一个静态类,如前所述,静态类是没有任何实例化它的对象的类。在C ++中,这可以通过将构造函数/析构函数声明为私有来获得。最终结果是一样的。
答案 7 :(得分:4)
在托管C ++中,静态类语法为: -
public ref class BitParser abstract sealed
{
public:
static bool GetBitAt(...)
{
...
}
}
......迟到总比没有好......
答案 8 :(得分:3)
这类似于C#在C ++中的方式
在C#file.cs中,您可以在公共函数中包含private var。 在另一个文件中,您可以通过使用以下函数调用命名空间来使用它:
MyNamespace.Function(blah);
以下是如何在C ++中使用它:
<强> 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();
答案 9 :(得分:3)
与其他托管编程语言不同,“静态类”在C ++中没有任何意义。您可以使用静态成员函数。
答案 10 :(得分:2)
正如此处所述,在C ++中实现此目的的更好方法可能是使用命名空间。但由于此处没有人提到final
关键字,因此我发布了C#中直接等效的static class
与C ++ 11或更高版本相似的内容:
class BitParser final
{
public:
BitParser() = delete;
static bool GetBitAt(int buffer, int pos);
};
bool BitParser::GetBitAt(int buffer, int pos)
{
// your code
}
答案 11 :(得分:2)
(许多)替代方法中的一种,但最优雅的方法(在我看来)(与使用名称空间和私有构造函数来模拟静态行为相比),是在C ++中实现“无法实例化的类”行为的方式将使用private
访问修饰符声明一个虚拟的纯虚函数。
class Foo {
public:
static int someMethod(int someArg);
private:
virtual void __dummy() = 0;
};
如果您使用的是C ++ 11,则可以通过在类声明中使用final
说明符来加倍努力以确保该类不被继承(以纯粹模拟静态类的行为)。限制其他类继承它。
// C++11 ONLY
class Foo final {
public:
static int someMethod(int someArg);
private:
virtual void __dummy() = 0;
};
尽管听起来很愚蠢和不合逻辑,但C ++ 11允许声明“无法覆盖的纯虚函数”,您可以将其与声明类final
一起使用,以完全并完全实现静态行为,因为这将导致结果类不可继承,并且伪函数不会以任何方式被覆盖。
// C++11 ONLY
class Foo final {
public:
static int someMethod(int someArg);
private:
// Other private declarations
virtual void __dummy() = 0 final;
}; // Foo now exhibits all the properties of a static class
答案 12 :(得分:0)
命名空间可能对实现&#34;静态类&#34;无效的一种情况。是在使用这些类来实现组合而不是继承时。命名空间不能成为类的朋友,因此无法访问类的私有成员。
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;
}
};
答案 13 :(得分:0)
class A final {
~A() = delete;
static bool your_func();
}
final
表示一个类不能被继承。
delete
对于析构函数意味着您不能创建此类类的实例。
这种模式也称为“util”类。
正如许多人所说的,C++ 中不存在 static class
的概念。
包含 namespace
函数的规范 static
在这种情况下首选作为解决方案。
答案 14 :(得分:0)
C++ 中没有静态类这样的东西。最接近的近似是一个只包含静态数据成员和静态方法的类。 类中的静态数据成员由所有类对象共享,因为它们在内存中只有一个副本,而不管类的对象数量如何。 类的静态方法可以访问所有其他静态成员、静态方法和类外的方法