C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++におけるプライベートデストラクタの挙動と活用方法

C++では、クラスのデストラクタをprivateとして宣言することが可能です。本記事では、デストラクタをprivateにした場合にどのような挙動になるのか、具体的なサンプルコードとともに詳しく解説します。

プライベートデストラクタとは

通常、デストラクタはpublicとして宣言されますが、あえてprivateにすることで、オブジェクトの生成や破棄の方法を制御できます。まずは基本となるケースから順番に見ていきましょう。

オブジェクトを生成しない場合

次のコードはデストラクタがprivateですが、コンパイルエラーにはなりません。これは、オブジェクトが一切生成されていないためです。

サンプルコード

#include <iostream>
using namespace std;
class my_class {
    private:
        ~my_class(){
            // プライベートデストラクタ
        }
};
int main() {
}

スタック上にオブジェクトを生成した場合

一方、次のようにオブジェクトを実際に生成しようとすると、コンパイルエラーが発生します。コンパイラはデストラクタにアクセスできないことを検出し、「処理完了後にオブジェクトを破棄できない」と判断するためです。

サンプルコード

#include <iostream>
using namespace std;
class my_class {
    private:
        ~my_class() {
            // プライベートデストラクタ
        }
};
int main() {
    my_class obj;
}

出力結果

[Error] 'my_class::~my_class()' is private

ポインタ宣言の場合

クラスへのポインタを宣言するだけであれば、エラーは発生しません。実際のオブジェクトが生成されていないからです。

サンプルコード

#include <iostream>
using namespace std;
class my_class {
    private:
        ~my_class() {
            // プライベートデストラクタ
        }
};
int main() {
    my_class *obj;
}

new演算子でオブジェクトを生成した場合

new演算子を使ってオブジェクトを生成した場合も、エラーは発生しません。コンパイラは「メモリからの解放はプログラマの責任である」と判断するためです。

サンプルコード

#include <iostream>
using namespace std;
class my_class {
    private:
        ~my_class() {
            // プライベートデストラクタ
        }
};
int main() {
    my_class *obj = new my_class;
}

delete文を追加した場合

しかし、ここにdelete文を追加してオブジェクトを削除しようとすると、デストラクタがprivateであるためにエラーが発生します。

サンプルコード

#include <iostream>
using namespace std;
class my_class {
    private:
        ~my_class() {
            // プライベートデストラクタ
        }
};
int main() {
    my_class *obj = new my_class;
    delete obj;
}

出力結果

[Error] 'my_class::~my_class()' is private

プライベートデストラクタの実用的な活用シーン

このように、デストラクタをprivateにすると、スタック上へのオブジェクト生成やdeleteによる明示的な削除が禁止されます。この特性を活かすことで、次のような設計が可能になります。

  • ヒープ専用オブジェクトの強制: オブジェクトの生成をnewによるヒープ確保のみに限定でき、スタックオーバーフローのリスクがある大型オブジェクトの誤った生成を防げます。
  • 寿命管理の一元化: 参照カウント方式のスマートポインタなど、オブジェクトの破棄タイミングをクラス自身が厳密に管理したい場合に有効です。

なお、privateデストラクタを持つオブジェクトを正しく破棄するには、friend関数やクラス内のpublicメンバ関数(例:destroy())からdelete this;を呼び出すといった工夫が必要です。この仕組みを理解しておくと、より安全で柔軟なクラス設計につながります。

  1. C++におけるカプセル化の基本と実装方法

    カプセル化(Encapsulation)とは、データとそのデータを操作するメソッドを1つのコンポーネントにまとめ、外部からの干渉から保護するオブジェクト指向プログラミングの重要な概念です。カプセル化を実現することで、「データ隠蔽(Data Hiding)」という非常に重要な概念が生まれます。C++では、ユーザー定義型であるクラスを使用してカプセル化を実現します。クラスは、データメンバとそれらを操作するメンバ関数をひとまとめにしたものです。以下に、C++のクラスを使ってカプセル化を表現するサンプルプログラムを示します。実装例#include <iostream> using name

  2. C++の識別子とは?命名ルールと具体例をわかりやすく解説

    C++における識別子(identifier)とは、変数、関数、クラス、モジュールなど、プログラマが定義するさまざまな要素に名前を付けて識別するために使われる名称です。識別子の命名には以下のルールがあります。先頭は半角アルファベットの大文字(A〜Z)、小文字(a〜z)、またはアンダースコア(_)で始める必要があります。2文字目以降は、英字・数字(0〜9)・アンダースコアを自由に組み合わせられます。識別子の中に「@」「$」「%」などの記号(句読点・特殊文字)を使うことはできません。大文字と小文字は区別されるC++は大文字と小文字を厳密に区別するプログラミング言語です。そのため、「Manpower」