C#には「staticメンバーだけを定義して、実体化(インスタンス化)は許可しない」ようなクラスを簡潔に定義する手段があります。
public static class MyHelper
{
public static int Add(int x, int y)
{ return x + y; }
}
staticクラスは状態を管理しない純粋ヘルパー(アルゴリズムや完全定数)を定義するのに便利です。代表的な例でいうと、System.Mathクラスが挙げられます。
なお、staticクラスからはサブクラスを派生させることもできません。
ちなみにJavaでもクラスをstaticキーワードで修飾することができますが、意味合いがまったく違います*1。C#のほうがキーワードに即していて直感的だとは思いますが。
C++/CLIおよびC++/CXでは以下のように書くことでC#のstaticクラス相当を記述できます。
public ref class MyHelper abstract sealed
{
public:
static int Add(int x, int y)
{ return x + y; }
};
しかし、従来の標準C++では、staticクラスを記述する文法は直接サポートされていません*2。
せいぜいできることと言えば、以下のようにデフォルトコンストラクタとデストラクタを隠ぺいして実体化を禁止するくらいしかなく、C#と比べて分かりやすさはともかく美しさに欠けます。
また、C++03以前では構文上で派生を禁止することができず、派生を禁止するにはC++11以降のfinal
キーワードを使う以外ありません。
class MyHelper
{
private:
MyHelper() {}
~MyHelper() {}
public:
static int Add(int x, int y)
{ return x + y; }
};
なお、C++11以降ではデフォルトコンストラクタとデストラクタをdelete指定することで、実体化を禁止することもできます。メンバーをdelete指定する場合はprivateではなくpublicとするのがセオリーです。
class MyHelper final
{
public:
MyHelper() = delete;
~MyHelper() = delete;
public:
static int Add(int x, int y)
{ return x + y; }
};
MSVCにはネイティブC++でもabstractキーワードを使えるように言語拡張が施されているので、abstract sealedまたはabstract finalを指定することでstaticクラスを記述することができるのですが、Clangなどでは使えません。移植性の高いコードを書きたい場合は注意が必要です。MSVCではコンパイルオプション/permissive-
を付けることで独自拡張を無効化することもできます。
2023-05-07追記:
C++17以前では言語仕様にお粗末なバグがあり、コンストラクタをdelete指定しているにもかかわらず集成体初期化による実体化ができてしまいます。前述のようにデストラクタもdelete指定しておけば、少なくとも削除はできなくなるので大抵のケースでは実質的に実体化を禁止できますが、さらにコンストラクタをexplicit指定しておけばC++17以前でも確実に実体化を禁止できます。C++20以降ではこの仕様バグが修正されています。
class MyHelper final
{
public:
explicit MyHelper() = delete;
...
};