構造体とクラス、関数とコンストラクタ、デストラクタの違いと利点を教えて下さい!

構造体とクラス、関数とコンストラクタ、デストラクタの違いと利点を教えて下さい! 授業や自分で勉強したりしてみたのですが、あまりクラスの利点がわからず…。 結局使わずプログラミングで色々やってしまっています。 何に使えるか、どんなことが良い点なのか教えていただきたいです!

C言語関連269閲覧xmlns="http://www.w3.org/2000/svg">100

ベストアンサー

0

構造体: 複数の変数の塊(集まり)です。 たとえば、 カードゲーム系のゲームを作るとしましょう。 最低でも、 ■ 名前 ■ レベル ■ タイプ (火属性とか) はありますよね。 カードによっては、 フィールド上 ( マップ上 ) に指定のキャラがいるときのみ有効 とかありますよね。 それをすべて変数でしたら.... ごちゃごちゃ... 配列にしても...扱いにくい... ( やり方にもよるだろうけど ) struct CARD { char Name[50]; // キャラ名 int iType; // 属性 ( 火なら 0, 水なら1 .... ) int Level; // レベル int Condition; // 出現条件 }; みたいにすれば、 struct CARD Domban; Domban.Name = "ドンバン"; Domban.iType = 3; Domban.Condition = 0; // 条件なし。ふつうのカード という風にできます。 これを配列と考えると... struct CARD card[10]; // カード10枚 struct CARD PC[10]; // PC側も // ここらへんでセットしてある if( card[0].iType == PC[0].iType ) ... とできます。 クラスはそれの拡張みたいなもので、 構造体は変数・配列・ポインタ・ほかの構造体 のみですが、 クラスはそれに 関数が追加されます。 関数は処理をまとめたものです。 たとえば、(本来はよくないかもしれませんが、例のため) ファイルの入出力に関して、 面倒だと思ったことありません? ファイルを開き、ファイルに書き込み、ファイルを閉じる 毎回この作業。 これを、 関数を呼び出せば、一発でできるようにしたいとすれば、 int WriteFile( char *filename, char *data ) { int ret; // 結果用 // ここで開く. できなければ -1 を返す. // ここまでくれば開けている. 書き込む. // ファイルを閉じる return ret; } のようにすれば、 呼び出しだけで済みます。 コンストラクタは、 クラスのインスタンス生成時に起動する特別なもの。 メンバ変数を初期化( 初期値を設定 )したり。 デストラクタは反対に、インスタンスが破棄 ( delete ) されるとき、メモリの破棄等を行う特別なもの。 利点... 説明しても難しくなりますが。 MFC を使わずに Windows API でGUI ( Excel、Word みたいに視覚的に操作できるやつ ) 作ったことありますか? Cでやると、 コントロールを操作 ( 生成・文字変更・文字取得等 ) を操作するためには、 最低でも、 ■ 親ウィンドウハンドル ( どのウィンドウにくっついているか ) ■ コントロールID ( どのコントロールか ) が必要です。 親ウィンドウハンドルを HWND hWnd コントロールID を int ControlID として HWND CreateButton( HWND hWnd, int ControlID, int X, int Y, int Width, int Height ); としてやるのもいいですが、 これじゃぁ、毎回親ウィンドウハンドルとコントロールIDを指定しなければいけない。 じゃぁ、グローバル変数にすれば? グローバル変数は推奨されていない。 やっても、 /* Button1 用 */ HWND hWnd1; int ControlID1; /* Button2 用 */ HWND hWnd2; int ControlID2; .... HWND CreateButton1( int X, int Y, int Width, int Height ); としても、 コントロールごとに作らなくてはいけない。 ソフトによっては、 選択する用のオプションボタンっていうのが 100近くあったり。 それの場合、最低でも、 100個のオプションボタン + 1 個の OK ボタン = 101 個 101個分作らなくてはなりません。 なおかつ、親ウィンドウ ( メインウィンドウ )も。です。 ですが、 クラスにして、 インスタンス化するときに 引数として親ウィンドウハンドルとコントロールID を渡して、コンストラクタでメンバ変数に設定できれば、 Button1.Create( int X, int Y, int Width, int Height ); のように引数の省略ができて楽になります。 このオブジェクト Button1 が 親ウィンドウハンドルとコントロールIDの代わりになるのです。 なので、いちいち毎回指定しなくていいのです。(もちろんオブジェクトは必要ですが。)

ThanksImg質問者からのお礼コメント

みなさま本当にありがとうございます! おかげでクラスがわかってきました。 全部参考になったのですが、例えがわかりやすかったのでベストアンサーにさせていただきました。

お礼日時:2015/12/17 19:08

その他の回答(5件)

0

必要ないならクラスなんか使わなくてもかまいません。 クラスを使うのはあくまでも手段ですから、手段を目的化するのはやめましょう。 ちなみに、C++では構造体はクラスの一種です。 structというクラスキーを使って定義したクラスを「構造体」といいます。 共用体もクラスの一種です。

0

そもそも、昔の言語(Cとか)にはクラスなんてなかったわけで、それでも当時は十分に使われていました。 しかし、システムが複雑化し、プログラミングが大規模になって、「このままでは限界だ」→「こういう仕組みのクラスというものを導入したら便利だ」となって、クラスというものがついたわけです。 たとえるなら、小さな会社ならワンマン社長がすべてを把握しているほうがやりやすいですが、大きくなると部署や社員に任せる必要が出てくる、みたいなものです。 だから、小規模なものを作っているうちは、クラスの利点がわからないのも無理はありません。 授業で使わされるなら、まあお作法だと思って使ってください。 自分で勝手にやっていいなら、無理して使わなくてもいいです。 ただ、大規模になってくるとそうもいってられなくなります。

0

クラスの利点は、情報隠蔽、継承、ポリモフィズムのオブジェクト指向が使えることなんですが、ようは、それまでの言語ではそれができなかった(するためには頭を使った)ので、不便だったので、言語の機能として付けたってことですよ。 ツッコミがはいるかもしれませんが、ざっくりと。 ポリモフィズムは、ようは引数の型が違っても、同じ事をするってことです。 それまでは、引数の型が違う場合は、関数名を分ける必要があった。 継承は、作った関数に更に付け加えて何かさせたい時に有効。 というのも、毎回新しく作ると、バグがあるかもしれないので、使い古して信頼性のあるものを使おう!というのと、すこし違うけど、やっていることはほぼ同じというものに有効。 それまでは、すでにあるソースコードをコピーして使っていた。 しかし、コピー元にバグがあると、コピーして作ったものも修正しないと行けない。 コピーが100もあると対処に時間がかかるので、コピーではなく、参照、、、みたいにしたんです。 情報隠ぺいは、それまではグローバル変数とかの変数名をオープンにしなければ行けなかった。 ところが、変数名をオープンにしちゃうと、別の誰かがその変数名を使ってしまう危険性がある。 それは大変こまるので、クラスという内部に変数名を固定し、使うときはクラスを通すことによって、バグを防いだ。 これらは、クラスやオブジェクト指向の一端ですが、ようは昔にはそれがなく、それがあることで便利になった、という解釈の方が、私は分かりやすいと思います。 一回の作りっぱなしなら、クラスを使わずとも、関数のみの方がむしろ簡単に作れるんですが。 大勢で、何年も開発期間があったり、複数のソフトを作ることが前提になると、オブジェクト指向の方が断然便利になるってわけです。 今あるもので、これって他にも使えそうだなー、って部分を独自の関数化(ライブラリ化)します。 自分だけのライブラリを作って、それを使いながら、時には修正すると、「あれ?こういう事ってできないのかな?」って思ったら、クラスにすると解決できることが多いと思います。 そういうライブラリかを、とりあえず色々としてみると、そのうち体感として分かると思いますよ。

0

基本的に C++ の場合で答えますよ。C# は別です。 (1)『構造体とクラス』 構造体とクラスは同じものです、唯一つの違いを除けば。アクセス指定のデフォルトが public なのが構造体、private なのがクラスです。 struct sample1 { int member1; }; class sample2 { int member2; }; member1 は public で、member2 は private となります。 ただ、ある種の迷信がありまして、コンストラクタ、デストラクタ、仮想関数、こういったものが構造体の中に書けないと信じている人は多いと思います。でも、それは迷信ですので。 ① 構造体の利点…メンバが全員 public なら構造体が適しています。コンストラクタ、デストラクタが居ても構いません。ただ、メンバへのアクセスがまったく制限されずに、それでも大丈夫なように作りこまれている必要があります。 ただし、private: って書いてしまえばそれまで。クラスと同じようなものになってしまいます。じゃ、なんではじめからクラスにしないんだよ…って反感をもたれる恐れがあると思いますが。 ② クラスの利点…必要最小限のメンバを public にします。あとは全員 private です。そうすることで今後行われるであろう機能追加・バグ修正・仕様変更の際に影響を受ける部分が少なくなります。 構造体でも同じですが、やはりそれを構造体でやってると、「何で?」って思われてしまいますので、そういう込み入ったことはクラスだけでやっておくと良いかも。 《参考》C# では構造体とクラスは別もの。構造体は値型、クラスは参照型です。見たところ上級者になると構造体を使い出す模様。慣れていないうちは皆さんクラスだけで済ましているみたいですね。当面はそれでも良いのかもしれません。構造体は何かと制約がありますので、若干使いにくいところがあります。 (2)『関数とコンストラクタ、デストラクタ』 〔コンストラクタ〕 インスタンス化される際、自動的に呼び出されるのがコンストラクタです。逆に言うと、自動的に…じゃない形で呼び出すのは大変です。new 演算子を使った特殊なやり方がありまして、それでやっと呼び出せるわけですが。 ですので一般の関数とコンストラクタの違いは、呼び出しを明示できるか否かです。 ① 「一般の関数」の利点 C 言語と同じ考え方でコーディングできますので、それがラクな人にとってはラクです。メンバを全員 public にしておけば「一般の関数」から自在にアクセスできますので、それで困らないのであれば確かにラクかもしれません。 ② コンストラクタの利点 メンバの初期化を行うにはコンストラクタしかありません。でも、慣れていない場合、初期化と代入は同一視されているところがあるように思います。ただの代入ならメンバ関数でも出来ますし、public メンバなら「一般の関数」でも出来てしまいます。 初期化じゃないにしろ、コンストラクタに書いておけばその通りの形でインスタンス化される、その状態から始まる…と想定することが出来ます。他のメンバ関数ではその前提で処理できますので if 文とかは少なくなります。もちろん、バグも減りますよ。だいたい、オブジェクトの状態が定まらない場面でバグが顕在化しますのでね。 〔デストラクタ〕 インスタンスが破棄される際に自動的に呼び出されるのがデストラクタです。コンストラクタと違い、呼び出しを明示することができます。やりたければ出来るのですよ。普通、やりませんが。 仮想関数にしたとき、他のメンバ関数と様相が異なってきます。他のメンバ関数だと、仮想関数によってオーバーライドが起きるわけです。要するに差し替え。基底クラス側の仮想関数は呼び出されません。(敢えて呼ばなければ) 仮想デストラクタの場合は違います。ちゃんと基底クラスのデストラクタも後で呼び出されますからね。当然ですが。 なお、デストラクタは仮想にするのが当然です。ただ、仮想関数が一つでも居るとサイズに影響が出ます。その問題があるため何も書かないとデストラクタは仮想にならないのです。 ③ 「一般の関数」の利点 特にありませんが強いて言えばコンストラクタの場合の①と同様に難しいことを考えずにラクにコーディングできるということでしょうか。でも、ちゃんと C++ を勉強すると、この点が逆転しますよ。デストラクタで済ませるほうが「何も考えない」っていう話。ものすごくラクなわけ。余計なことを心配しないで済むのですから。 ④ デストラクタの利点 メモリ割り付けと解放、ファイルのオープンとクローズ、いずれも対称性が大事です。片一方だけじゃ、駄目ですよね。これを確実なものにする上でデストラクタが大事ですよ。 C 言語の場合だとアプリケーションプログラムを作りこんでいる最中に、こういうことを気にしてたんですよね。C++ では思考の対象から外すことができます。ただ、デストラクタに書けば良いのですから。 《参考》C# の場合、コンストラクタは概ね同じ考え方で良いと思います。でも、デストラクタは違った見方が必要かもしれません。オブジェクトがいつ破棄されるかわかりませんのでね。using とかってありますよね。ファイルがオープンしっ放しになってしまうのを防ぐためには、デストラクタでは無理だっていうわけ。 『結局使わずプログラミングで色々やってしまっています』 通常、そうなります。歴史を辿っているようなものです。まもなく変わってくると思いますよ。 『何に使えるか、どんなことが良い点なのか』 何に使えるか、考えないほうが良いと思います。特に、アプリケーションに使えるとは思わないで下さいね。そうじゃなくて、アプリケーションを作る時に考えなくて良いよう、放ったらかしにできるよう、そういうために用意された仕組みですので。 良い点…についても、これは良し悪しというよりもオブジェクトの秩序を保つための仕組みなのです。オブジェクトが暴れださないよう、箍(たが)が外れないよう、きっちり定義する。そういう考え方が合ってると思います。

0

構造体はそのままの意味 データを構造化する事が出来る クラスはインスタンスしてオブジェクト化し、それをプログラミングの中で使用します。 クラス自体はそのオブジェクトの遺伝子の様な物で、 貴方が神で、人と言う情報や機能を書いていきます。要するに設計図の様な物。 最後に今作ったクラスをインスタンスしたら、人間の出来上がり クラスには、その中で必要な情報と機能を書いて行きます。 またクラスは継承して、進化した物も作れます。 例えば、既存のクラスが不良品の場合、既存のプログラムを崩さず必要な情報だけを親クラスから取得し、新たに機能を実装する。そんな感じです。