お世話になります。ミミです。
まず、keisan クラス (class keisan)というものを作り、
その中に、メンバ関数
int plus(int A, int B);
int minus(int A, int B);
があるとします。(ソースは省略します)
そして、それを hoge クラスで使うとした場合、
現在私は、
hoge.h にメンバ変数として「keisan m_clsKeisan;」と宣言し、
cpp の中では、「m_clsKeisan.plus(nNumA, nNumB);」
という感じで使っていました。
コンパイルも通りますし、私の意図する動きもしてくれますが、
ヘッダ(hoge.h) に int 型のメンバ変数を宣言する様な感じで、
クラスもインスタンス化していいものなのか今更ではありますが、判断ができません。
入門書などのサンプルでは、1つのファイル(拡張子は .c だった気がします。)
に、プロトタイプ宣言や、main()が書かれている物も見かけたことがあり、
h と cpp は便宜上分かれているものなんだと考えており、
特にヘッダにインスタンス宣言することも違和感を感じません。
私は「動いているから、こういう書き方も出来る物なんだ」と固定概念を
持ってしまっています。
一般として、上記の様な利用法はせずに、
hoge.h には、「keisan* m_pKeisan;」とポインタ変数だけ定義して、
hoge.cppのコンストラクタで、「m_pKeisan = new keisan;」により実体化し、
デストラクタで 「delete m_pKeisan;」
とすべきなのでしょうか?
今更こんな初歩的な質問で申し訳ありませんが、
何卒アドバイスのほど、よろしくお願いいたします。
すみません、ミミです。
先ほどの環境は VC++6.0、MFC使用です。
また、追加で申し訳ありませんが、
ヘッダに宣言したメンバ変数は、スタック領域に確保され、
一方、newで確保したものは、ヒープ領域に確保されるという事ですので、
メモリの節約を考えるなら、なるべく new - deleteを使用すべきなのでしょうか?
> クラスもインスタンス化していいものなのか
まったく問題ありません。
ただし、keisan クラスのように、処理に必要な全てのデータが引数で渡される(言い換
えれば、メンバ変数を持っていなくて、単なる関数の集合としてのクラス)のであれ
ば、plus とか minus とかを static 関数にしてしまえば、インスタンス化とかで悩ま
なくても済むと思います。
ミミです。
シャノン様、ご返信ありがとうございます。
>まったく問題ありません。
今までも、(やはりいくつかのメソッドを持つ) CString クラスも、メンバ変数としてインスタ
ンス化
していましたし、この理由もあって、自分の中では特に違和感を感じていませんでした。
今回、問題無いとお聞きして、安心いたしました。
>static 関数にしてしまえば
今回は、hoge クラスでしか扱わない事が分かっていたので、コーディングした当時は、
クラスをインスタンス化して使おうと考えてしまいました。
(単純な処理の固まり(keisan)と、それを制御する固まり(hoge)とを分離したかった為です。)
static宣言すれば、確かにインスタンス化とか悩まなくてすみそうですね。
盲点でした。
# やはりまだまだ経験が足りないようです、自分。
一方、厚かましいとは思いますが、
>メモリの節約を考えるなら、なるべく new - deleteを使用すべきなのでしょうか
についてもご教授頂けたら幸いです。
> メモリの節約を考えるなら、なるべく new - deleteを使用すべきなのでしょうか
そんなことはありません。
というか、場合によっては、new - delete を使う方がメモリは多く食うかもしれません
(微々たる差でしょうけど)。
また、new - delete を使ったメモリアクセスは遅いです。小さいオブジェクトなら、普
通に変数として宣言してしまった方が高速になります。
関数は静的だろうが動的だろうが消費するメモリ量は変わらないため、keisan クラスが
メンバ変数を持たず、static 関数だけで構成されるようなものであれば、new -
delete を使う必要は無いと思います。
ミミです。
シャノン様、ご返信ありがとうございました。
おかげさまで、本件は自分の中で解決に至りました。
ご教授ありがとうございました。
>また、new - delete を使ったメモリアクセスは遅いです。
「ヒープ領域はスタック領域と比べると、メモリの使用可能域は大きい分、
やはりアクセス速度は劣る」と、以前、会社内で学習した事があります。
シャノン様のご指導も、まさにこの事ですね。…再認識しました。
本件については文頭の通り、解決扱いですが、
シャノン様のご回答文で一部理解出来ていないところがありますので、
追加で質問させてください。
>メンバ変数を持たず、static 関数だけで…
と、2回のご回答共に「メンバ変数を持たない」事が前提としてご回答を頂きましたが、
これは、
『static で指定したメソッドは、実体化しなくとも使えるが、仮にそのメソッドの中で
(keisanクラスの)メンバ変数を使用していた場合、メンバ変数は実体化されていないため
変数にアクセスできない。だから、メンバ変数を持たない事が前提。』
と自分の中で解釈いたしました。
この認識で間違っておりませんでしょうか?
重ねての質問で申し訳ありませんが、よろしくお願いいたします。
staticなメンバ変数に関してはstaticメソッドからアクセスしてもOKです。
> static で指定したメソッドは、実体化しなくとも使えるが、仮にそのメソッドの中で
> (keisanクラスの)メンバ変数を使用していた場合、メンバ変数は実体化されていない
> ため変数にアクセスできない。
メンバ変数は持ってもいいけど、staticメソッドから使わないようにすることをいって
いるのに、
> メンバ変数を持たない事が前提
となるのはなんかおかしいようですけど。
(メンバ変数を使わない事が前提になるのかな?)
例えば以下のようなクラスがあります。
class foo
{
int m_nVal;
static int s_nVal;
public:
foo() : m_nVal(0)
{
}
void dec()
{
m_nVal--;
}
int getVal() const
{
return m_nVal;
}
static inc()
{
s_nVal++;
}
static int get()
{
return s_nVal;
}
};
int foo::s_nval = 0;
// static関数を使ってみる
foo::inc();
int static_val = foo::get();
// インスタンス変数を使ってみる
foo f;
f.dec();
int instance_val = f.getVal();
typo
> int foo::s_nval = 0;
int foo::s_nVal = 0;
結局、問題になるのはクラスのインスタンスがないとアクセスできない物は
staticなメンバー関数からはアクセスできないと言う部分だけだと思います。
そこさえ抑えておけばいいだけだとおもいます。
staticなメンバー関数はクラスのインスタンスが無くても呼び出せますから
その時点でクラスのインスタンスが存在するかどうかの保障はありませんし、
例え、インスタンスが他の場所に存在していてもそれを覗き見る術がありませんから。
> 2回のご回答共に「メンバ変数を持たない」事が前提としてご回答を頂きましたが
失礼。
俺の最近の考えでは、「クラスとは、インスタンス化するのが主な使い方であり、メン
バ変数がその核であり、メンバ関数はその変数を処理するために存在する」ということ
になっています。
この考えから、2回とも「関数の集合のようなクラス」とも書きましたが、静的なメン
バ関数しか持たないクラスであれば、そもそもクラスにする意味が薄いと考えていま
す。
static メンバ変数というのもありますが、こんな風に考えているので、すっかり忘れて
ました。