- ベストアンサー
C++ データの扱い方の種類を教えて下さい
現在、資料の見よう見まねで機能毎にソースとヘッダを複数分けているのですが、 クラスを超えてデータを管理・変更する方法がわからずに、 現在全てのソースのヘッダーで 『extern』 宣言をして共有してしまっています。 (1変数・1配列単位でちまちまと。) できれば、 1.クラスを超えて、プログラムが終わるまで扱っていたいデータ。 2.数クラスをまたいだら、削除してしまいたいデータ。 に適した方法と 「データをまとめて扱い易くする方法」を詳しく教えて頂けると幸いです。 実装方法は自分で何とか頑張って勉強してみるつもりですので、 個人的な使い勝手で構いませんので『種類と用途』をどうか教えて下さい。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
こんばんは。 ・1 シングルトン ・2 勝手に消えると言う事でしょうか? 其れならば、リファレンスカウンタ式のスマートポインタ辺りで良さそうです。 1の方はテンプレート化すると使いまわせます。但し、参照を返しているので、途中で消すのは帰って危険かもしれません。 アラもあるとは思いますが、以下参考程度に。 template<class __Tp> struct SingleTongue { typedef typename SingleTongue<__Tp> _Self; typedef typename __Tp value_type; typedef typename __Tp* pointer; typedef typename __Tp& reference; static reference GetInstance() { if(instance)return *instance; ::atexit(&_Self::Release); instance = new value_type(); return *instance; } static reference GetInstance(const _Self& r) { if(instance)return *instance; ::atexit(&_Self::Release); instance = new value_type(r); return *instance; } template<class __A> static reference GetInstance(const __A& a) { if(instance)return *instance; ::atexit(&_Self::Release); instance = new value_type(a); return *instance; } template<class __A, class __B> static reference GetInstance(const __A& a, const __B& b) { return GetInstance(value_type(a, b)); } private: static void Release() { delete instance; instance = NULL; } static pointer instance; }; template<class __Tp> typename SingleTongue<__Tp>::pointer SingleTongue<__Tp>::instance = NULL; struct MyData { explicit MyData(int _a = 0, int _b = 0) : a(_a), b(_b) { } int a; int b; }; int main() { typedef SingleTongue<MyData> STMyData; STMyData::reference rInst = STMyData::GetInstance(1); //以下の様にしても作成出来る //STMyData::reference rInst = STMyData::GetInstance(1, 2); //STMyData::reference rInst = STMyData::GetInstance(STMyData(2, 7)); rInst.a; rInst.b; return 0; }
その他の回答 (4)
- BLK314
- ベストアンサー率55% (84/152)
これって”設計"の問題ではないでしょうか? >「データをまとめて扱い易くする方法」 これには2段階あると思われます A.クラスレベルでまとめる 要するに関連するデータを1つのクラスでまとめて管理するということです B. モジュールレベルでまとめる 1クラスを1つのモジュールとしてとらえてもよいのですが、 非常に密接に関連する複数のクラスをまとめて1つのモジュールとしたほうが 分かりやすい場合もあります。 具体的には、ヘッダには外部へのインターフェースとなるクラス1つだけを書 き、cppにはそのクラスの実装とともに、内部的に使うクラスの宣言/実装も書 いてしまう方法です おそらく、"数クラスをまたいだら削除してしまいたい"というのは 実装の都合上、一時的にだけ使われるようなデータを指すと思われます。 こういうのが、プログラム全体でどこからでもアクセスできてしまうのは ”百害あって一理なし"なのでモジュール内に隠ぺい (cppでstatic宣言する) するとプログラムの見通しが良くなると思います。
お礼
ご回答有難うございました。 私にはまだ難しいですが、将来的にはこういう事を当たり前に出来ないとまずいのですね。 ありがとうございました。 そしてこの場を借りて、 回答して下さった方々ありがとうございました。 新米でデータの管理はみんなどうしてるのか判らず 進むべき方法が判らなかったので、本当に勉強になりました。 別の問題に囚われ返答が遅くなって申し訳ありません。 メモにのこして順番に理解して行かせて頂きます。 みなさんありがとうございました。
- zwi
- ベストアンサー率56% (730/1282)
1.クラスを超えて、プログラムが終わるまで扱っていたいデータ。 2.数クラスをまたいだら、削除してしまいたいデータ。 両方ともですが、そのデータこそ「オブジェクト」なので組になるデータ単位でクラスにしてはいかがでしょう? 処理を主体で考えておられるようですが、データを主体に考えるのがオブジェクト指向です。データの処理は出来るだけクラスの内部に隠蔽して、外部とのやりとりはメンバ関数や演算子のオ-バロ-ドを通して行うべきだと思います。と言うかそうしないとクラスを使う意味が無い気がするんですが。 クラス化すれば、データの確保と削除はクラスのインスタンスの生成と消滅で制御できます。 [補足] 2.数クラスをまたいだら、削除してしまいたいデータ。 なんにしても確保したところと待ったく別の所で削除するのは危険極まりないので、確保したソースコードの見える範囲で必ず削除しましょう。
お礼
ご回答ありがとうございました。 いつか利用できるよう勉強を進めて行きたいと思います。
- Tacosan
- ベストアンサー率23% (3656/15482)
具体的に「こういう方法」というのは示しません. あと, 「どのくらい手間がかかるのか」も無視します. 「データをまとめて扱い易くする方法」というだけなら, 構造体なんてまさにそのためですよね. だから, 「論理的にまとめて管理しなきゃならないデータ群」を構造体としてまとめると簡単になったりする. その他の部分だけど, 「データの生存期間」だけを考えても無意味で, 「そのデータがどこで使われるのか」も考える必要があるんじゃないでしょうか. 「プログラムを実行している間保持しておかなきゃならないデータ」であっても, 「使う場所が限定されている」ならグローバルにする必要性はないです... というか, グローバルにするな. 「数クラスをまたいだら削除したいデータ」もグローバルに定義する価値はなくって, 必要なところで作って不要になったところで捨てればいい. 場合によっては shared_ptr あたりが使えるかもしれない. いずれにしても, 可能なら引数として渡すべきでしょう.
お礼
>「そのデータがどこで使われるのか」も考える必要があるんじゃないでしょうか. そうですね、今はまだ頭がいっぱいいっぱいですが、 そういう事もいずれ考えられるように努力しようと思います。 >いずれにしても, 可能なら引数として渡すべきでしょう. そうですね・・今は引数はせめて3~4個と と決め付けていましたが 利用元が限られるのであればもっと引数に頼る方がシンプルで良いのかもしれませんね。 考え方等為になるご意見、ありがとうございました。
- LOHA
- ベストアンサー率52% (203/388)
>機能毎にソースとヘッダを複数分けている というのがちょっと良く分からないのですが、ヘッダファイル(.h)にはクラスや、関数、変数の宣言を、実装ファイル(.cpp)では、そのヘッダファイルをインクルードして、宣言したモノの定義を書くだけです。 で、別のファイルで定義したクラスを使いたいソースファイルがあったらその都度必要なヘッダファイルをインクルードすればいいはずです。 共通のヘッダファイルを色んなファイルでインクルードしたい場合は、インクルード処理をまとめたヘッダファイルを作成したりすれば楽です(ただし循環参照には気をつける)。 >1.クラスを超えて、プログラムが終わるまで扱っていたいデータ。 ですが、超楽ーに実装するのでしたら、グローバル変数にするのが手っ取り早いと思います(当然グローバル変数は避けた方がいいですが、名前空間とか使えばスコープを制限できるので工夫次第ですね)。 あるいはNo.1さんが挙げられているようにシングルトンパターンを利用するのも一つの手でしょう。
お礼
>インクルード処理をまとめたヘッダファイルを作成したりすれば楽です 成る程、1cpp 1hという利用しかしていませんでしたが、そういう方法も有るのですね; >グローバル変数と名前空間 成る程。確かに名前付けが怖かったですが、名前空間を使えば便利な名前で使えるのですね。 今すぐにでも簡単に使えそうな方法のご紹介、本当にありがとうございます
お礼
ご回答ありがとうございます。 シングルトン・スマートポインタ 両方初めて聞きました。 こういう方法が有るのですね。 軽く調べてみただけでも何やら良さそうな感じがします。 ご助言有難うございます!