プロが教えるわが家の防犯対策術!

プログラミング言語はC++
C++を触り始めたばかりの素人です。
コンストラクタとデストラクタについて質問です。

下記に参考にしているウェブページから簡潔にしてコードを書いてみました。
コンストラクタ、デストラクタの中はそれぞれに、○○が呼び出されましたと書いてあるだけでよく分からなかったので別のウェブページを見たら
コンストラクタは Sample::Sample(){ n=0; } みたいな例があったのですが、このように変数に予め何かの値を代入しておくという事で合ってますか?
デストラクタは理解できていません。
下記の例では、どのような処理を書けばいいのでしょうか?

#include<iostream>
using namespace std;

class Sample
{
private:
int n;
public:
void Show();
Sample();
~Sample();
};
void Sample::Show()
{
cout << n << endl;
}
Sample::Sample()
{
//n=0;
std::cout << "コンストラクタが呼び出されました" << std::endl;
}
Sample::~Sample()
{
//どんな処理?
std::cout << "デストラクタが呼び出されました" << endl;
}

main()
{
Sample sample;
sample.Show();
return 0;
}

実行結果
コンストラクタが呼び出されました
1     ←コンストラクタ関数内の//を削除で0になることは確認
デストラクタが呼び出されました

A 回答 (3件)

コンストラクタには前準備(初期化)、デストラクタには後始末を書きます。


たとえば:

class testfile {
FILE* fp;
public:
textfile(const char* fname) { fp = fopen(fname,"r"); }
~textfile() { fclose(fp); }
...
};
    • good
    • 0
この回答へのお礼

episteme様へ

int型の変数を定義するだけじゃデストラクタは必要がないみたいですね。
私の見た例では、提示したソースコードのようにint型の変数を1つ定義してあるだけだったので、理解に苦しみましたが、他の例を挙げてもらえたおかげで理解できたと思います。
ファイルの入出力でコンストラクタとデストラクタを使うのですね。
C言語もやったことはありますが、確かに開いたファイルは閉じろと言われてたのを思い出しました。
こういう前準備と後始末の一連の動作をコンストラクタとデストラクタの関数で行うと、なるほどと思いました。
ありがとうございました。

お礼日時:2012/06/03 15:44

この例だとデストラクターでやる処理は何もないですね。


このクラスから生成されたオブジェクトが消えるときに、消し残したものはできませんので。

たとえば、このクラスの中でnewなどでほかにメモリーを確保している場合、ネットワークの接続をしている場合は、このクラスが消えるときに明示的にそれらの終了処理を書いておかないとそれらのリソースが残るので、デストラクターでの処理が必要になります。

たとえば、
#include<iostream>
using namespace std;

class Sample
{
private:
int* n;
public:
void Show();
Sample();
~Sample();
};
void Sample::Show()
{
cout << n[0] << endl;
}
Sample::Sample()
{
n = new int[1]; // メモリーを動的に確保
for (int i = 0; i < 1; i++) {
n[i] = 0;
}
std::cout << "コンストラクタが呼び出されました" << std::endl;
}
Sample::~Sample()
{
delete [] n; // デストラクタで確保したメモリーを解放
std::cout << "デストラクタが呼び出されました" << endl;
}

int
main()
{
Sample sample;
sample.Show();
return 0;
}

ただ、今時はSTLやスマートポインターを使ってプログラムを書くのがC++では普通だと思いますので、デストラクターで明示的に何かの処理を書くのは珍しくなってきているかもしれません。メンバー変数をvectorやstring、スマートポインターにしてあるとそれらのデストラクターがちゃんとメモリーを解放してくれますし、メモリー周りのバグを減らすためにそういう書き方をするほうが推奨だと思いますので。
    • good
    • 0
この回答へのお礼

hanabutako様へ

質問時に提示したソースコードは、ごちゃごちゃしていたコメントを消して、自分好みに変数名を少し変えただけで処理的には何もいじってなく、ほぼ丸々コピーした状態のものです。
実際に使っている例ではなく、単に書き方を説明しているだけなのかなと思えてきました。
説明の書いてあるページには、newや、他の方にご回答頂いた例のファイルの入出力等の実際に使っている例はなく理解するには難しいものでしたが、提示したソースコードを修正して頂いたおかげで簡潔で分かりやすかったです。
ありがとうございました。

お礼日時:2012/06/03 15:51

コンストラクタはクラスのインスタンスが発生した際に呼び出されます。


主にメンバ変数の初期化に使います。また、初期化時に行いたい処理も書けます。例えば、ミューテックスやセマフォハンドルの生成とか、クラスをのサブルーチンで共通で使うファイルを開くとか。

逆にデストラクタは、インスタンスが消滅する際に呼び出されます。
使っていたハンドルが閉じてなかったら閉じるとか、開いてあるファイルを閉じるとか。

コンストラクタはインスタンスの生成で呼ばれますから、newした時や、newしない変数定義に呼ばれます。

void test()
{
Sample sam; //samのインスタンス発生なので、コンストラクタ呼び出し
Sample* pSam; //pSamのインスタンスはまだ発生してないから、コンストラクタは呼び出さない

sam.Show();

pSam = new Sample(); //pSamのインスタンス発生なので、コンストラクタ呼び出し

pSam->Show();

delete pSam; //pSamのインスタンス消滅なので、デストラクタ呼び出し

return; //samのインスタンス消滅なので、デストラクタ呼び出し
}
    • good
    • 0
この回答へのお礼

unacyo様へ

ミューテックス、セマフォハンドルの生成・・・例を挙げて頂けたのはありがたいのですが、調べてもよく分かりませんでした。
これらは、メモしておいて今後、理解したいと思います。すみません。
初期化を行うことと呼び出しのタイミングは理解しました。
ありがとうございました。

お礼日時:2012/06/03 16:04

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!