C++の静的データメンバ(staticメンバ変数)とは?仕組みと使い方を実例で解説
静的データメンバとは
静的データメンバ(staticデータメンバ)とは、staticキーワードを使って宣言されるクラスのメンバです。クラスから生成されるオブジェクトの数に関わらず、静的データメンバの実体はクラス内にただ一つだけ存在します。これは、すべてのオブジェクトがこの静的データメンバを共有しているためです。また、最初のクラスオブジェクトが生成されるタイミングで、静的データメンバは自動的にゼロで初期化されます。
この特性を活かすと、「生成されたオブジェクトの総数」のように、クラス全体で共通して管理したい値を持つことができます。
静的データメンバの宣言構文
静的データメンバは、次のような構文で宣言します。
static data_type data_member_name;
上記の構文において、staticは静的メンバであることを示すキーワードです。data_typeにはintやfloatなどC++の任意のデータ型を指定し、data_member_nameにはそのデータメンバに付ける名前を記述します。
なお、クラス内で宣言した静的データメンバは、クラスの外側で「int Student::objectCount = 0;」のようにスコープ解決演算子(::)を使って定義・初期化する必要がある点にも注意してください。
C++の静的データメンバのサンプルプログラム
ここでは、静的データメンバを使って生成されたオブジェクトの個数をカウントするプログラムを紹介します。
コード例
#include <iostream>
#include<string.h>
using namespace std;
class Student {
private:
int rollNo;
char name[10];
int marks;
public:
static int objectCount;
Student() {
objectCount++;
}
void getdata() {
cout << "Enter roll number: "<<endl;
cin >> rollNo;
cout << "Enter name: "<<endl;
cin >> name;
cout << "Enter marks: "<<endl;
cin >> marks;
}
void putdata() {
cout<<"Roll Number = "<< rollNo <<endl;
cout<<"Name = "<< name <<endl;
cout<<"Marks = "<< marks <<endl;
cout<<endl;
}
};
int Student::objectCount = 0;
int main(void) {
Student s1;
s1.getdata();
s1.putdata();
Student s2;
s2.getdata();
s2.putdata();
Student s3;
s3.getdata();
s3.putdata();
cout << "Total objects created = " << Student::objectCount << endl;
return 0;
}実行結果
上記プログラムの出力は次の通りです。
Enter roll number: 1 Enter name: Mark Enter marks: 78 Roll Number = 1 Name = Mark Marks = 78 Enter roll number: 2 Enter name: Nancy Enter marks: 55 Roll Number = 2 Name = Nancy Marks = 55 Enter roll number: 3 Enter name: Susan Enter marks: 90 Roll Number = 3 Name = Susan Marks = 90 Total objects created = 3
プログラムの解説
このプログラムでは、Studentクラスが学生の出席番号(rollNo)、名前(name)、点数(marks)という3つのデータメンバを持っています。その中でobjectCountだけが静的データメンバであり、Studentクラスのオブジェクトが何個生成されたかを記録しています。
コンストラクタStudent()は、新しいオブジェクトが生成されるたびに呼び出され、そのたびにobjectCountを1ずつインクリメントします。これにより、オブジェクトの生成回数が自動的にカウントされる仕組みです。
クラス定義のポイント
クラスには、ユーザーからデータを入力するgetdata()と、入力されたデータを表示するputdata()という2つのメンバ関数が用意されています。該当するコード部分は以下の通りです。
class Student {
private:
int rollNo;
char name[10];
int marks;
public:
static int objectCount;
Student() {
objectCount++;
}
void getdata() {
cout << "Enter roll number: "<<endl;
cin >> rollNo;
cout << "Enter name: "<<endl;
cin >> name;
cout << "Enter marks: "<<endl;
cin >> marks;
}
void putdata() {
cout<<"Roll Number = "<< rollNo <<endl;
cout<<"Name = "<< name <<endl;
cout<<"Marks = "<< marks <<endl;
cout<<endl;
}
};main関数の処理の流れ
main()関数の中では、Studentクラスのオブジェクトとしてs1、s2、s3の3つを生成し、それぞれに対してgetdata()とputdata()を呼び出しています。最後に、objectCountの値を表示して、生成されたオブジェクトの総数を確認します。
int main(void) {
Student s1;
s1.getdata();
s1.putdata();
Student s2;
s2.getdata();
s2.putdata();
Student s3;
s3.getdata();
s3.putdata();
cout << "Total objects created = " << Student::objectCount << endl;
return 0;
}実行結果の最後にある「Total objects created = 3」という出力から、3つのオブジェクトが生成され、それが静的データメンバによって正しくカウントされていることが分かります。このように静的データメンバを使うことで、個々のオブジェクトに依存しないクラス全体で共有されるデータを簡単に扱えます。
-
C++で学ぶ循環キュー(リングバッファ)データ構造の実装方法
キュー(Queue)は、要素の集合を格納する抽象データ構造の一つです。キューはFIFO(First In, First Out:先入れ先出し)という仕組みを採用しており、最初に挿入された要素が最初に取り出されます。キューは線形データ構造として表現できますが、単純な配列で実装すると問題が発生する場合があります。挿入操作と削除操作を繰り返すうちに、先頭(front)と末尾(rear)の位置が配列の後方へ移動していきます。その結果、実際には空きスペースが残っているにもかかわらず、論理的な制約によって新しい要素を挿入できなくなることがあります。この問題を解決するために使われるのが循環キュー(Circu
-
C++で二分木を簡潔にエンコード・デコードする方法
二分木の簡潔なエンコーディングとはここに一つの二分木があるとします。ご存知の通り、二分木の簡潔なエンコーディング(succinct encoding)とは、理論上の最低限に近い記憶領域で木の構造を表現できる手法です。構造的に異なる「n個のノードを持つ二分木」の総数は、n番目のカタラン数(Catalan number)によって表されます。nが大きくなると、この数はおよそ4^nに近づくため、エンコードには最低でも log₂(4^n) = 2n ビットが必要になります。したがって、簡潔な二分木は 2n + O(n) ビット程度で表現できることになります。たとえば、次のような二分木が入力として与えられ