C++ で静的キーワードを使用する
このガイドでは、C++ で static
キーワードを使用する方法のいくつかの方法について説明します。
C++ で static
キーワードを使用して静的期間の変数を宣言する
static
キーワードを使用して、静的期間のローカル変数を宣言できます。名前が示すように、静的期間のローカル変数は、変数が宣言されているブロックがスコープ外になった後でも、その値がメモリ内でアクティブなままであることを意味します。
基本的に、これらのローカル変数は、定義されている関数呼び出しの間に値を保存できます。incrementCount
関数には、0
の値で初期化される count
という変数があることに注意してください。count
属性は、プログラムが終了するまでアクティブなメモリ領域に割り当てられます。したがって、incrementCount
を呼び出すたびに、指定された整数に 1つの単位が追加されます。
#include <iostream>
using std::cout;
using std::endl;
int incrementCount() {
static int count = 0;
return ++count;
}
int main() {
for (int i = 0; i < 20; ++i) {
if (i % 2 == 0) incrementCount();
}
cout << incrementCount() - 1 << endl;
return EXIT_SUCCESS;
}
出力:
10
C++ で static
キーワードを使用してクラスの静的メンバーを宣言する
一方、static
キーワードは、クラスの静的データメンバーを宣言するために使用されます。これらのメンバーは、クラスの特定のインスタンスではなく、クラスタイプ自体に関連付けられています。したがって、特定のクラスに静的データメンバーを定義すると、このクラスタイプのすべてのインスタンスは、データメンバーに対して同じ値を持ちます。プライベートメンバーを持つのとは異なり、前者はメモリに単一のコピーを持ちます。後者の機能により、静的データメンバーはクラスメモリフットプリントの観点から効率的になります。
静的
データメンバーは、通常のデータメンバーとは異なる方法で定義および初期化されます。static
メンバーは、クラス内で宣言し、関連するソースファイルのクラス外で定義する必要があります。static
キーワードは、クラス内の宣言でのみ使用されます。コンストラクターで初期化できる static
データメンバーはなく、const
整数型でない限り、クラス本体内で初期化することはできません。後者のタイプは、初期値を指定せずにクラス本体の外部で定義する必要があります。次の例は、文字列リテラルで初期化され、後で setNewName
関数で変更される static
データメンバーname
の簡単な使用法を示しています。
#include <iostream>
#include <string>
#include <utility>
using std::cin;
using std::cout;
using std::endl;
using std::string;
class MyClass1 {
private:
static string name;
string nickname;
public:
explicit MyClass1(string n) : nickname(std::move(n)){};
static string getName() { return name; }
static void setNewName(std::basic_string<char> s) { name = std::move(s); }
string getNickname() { return nickname; }
~MyClass1() = default;
};
string MyClass1::name = "Static name";
int main() {
MyClass1 m1(string("April"));
MyClass1 m2(string("Maude"));
cout << MyClass1::getName() << endl;
MyClass1::setNewName("New name");
cout << MyClass1::getName() << endl;
return EXIT_SUCCESS;
}
出力:
Static name
New name
あるいは、クラスには、どのオブジェクトにもバインドされていない static
関数メンバーが含まれている可能性があるため、本体で this
オブジェクトを参照することはできません。一般に、これらの関数は、次のサンプルプログラムに示すように、静的
データメンバーのように個別の宣言と定義を持つ必要はありません。それでも、ほとんどの現代的なスタイルガイドでは、通常、プログラマーが 2つを切り離す必要があります。
#include <iostream>
#include <string>
#include <utility>
using std::cin;
using std::cout;
using std::endl;
using std::string;
class MyClass1 {
private:
static string name;
string nickname;
public:
explicit MyClass1(string n) : nickname(std::move(n)){};
static string getName() { return name; }
static void setNewName(std::basic_string<char> s) { name = std::move(s); }
string getNickname() { return nickname; }
static bool compareStrings(const std::basic_string<char>& s1,
const std::basic_string<char>& s2) {
if (s1 == s2)
return true;
else
return false;
}
~MyClass1() = default;
};
string MyClass1::name = "Static name";
int main() {
MyClass1 m1(string("April"));
MyClass1 m2(string("Maude"));
MyClass1::compareStrings(m1.getNickname(), m2.getNickname())
? cout << "strings are equal" << endl
: cout << "strings are not equal" << endl;
MyClass1::compareStrings(MyClass1::getName(), MyClass1::getName())
? cout << "strings are equal" << endl
: cout << "strings are not equal" << endl;
return EXIT_SUCCESS;
}
出力:
strings are not equal
strings are equal