• ベストアンサー

C++では構造体がメンバ関数をもてることについて

仕事ではC言語を使っています。7年ぶりくらいにC++を勉強しなおす気になりました。勉強し始めて疑問に思ったことがあります。 C++では構造体もメンバ関数やコンストラクタ、デストラクタをもてるようですが、なぜそのような仕様になったのでしょうか?クラスでできることをわざわざ構造体(や共用体)でも出来る必要性を感じません。(きらいなら使わなければいいだけのことですが。) 学生時代にC++を勉強したとき使っていた本(※)にそのような記述が無かったような気がします。 ※柴田望洋著:プログラミング講義C++、ソフトバンクブックス、1997 なぜそのような仕様になっているのか、経緯や必要性について教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.3

質問者さんがお望みのこと全てではありませんが、D&E (C++の設計と進化)という本の 94~95ページに、なぜclass と structという二つのキーワードが ほぼ同じ機能を持っているのかということについての説明があります。 詳しくは買うなり図書館に行くなりして実際に読んでもらうとして、 簡単にまとめると、structをCでの機能をのままにすることによって C++文脈でのclass、C文脈でのstructというように概念的に二つに分かれて しまうのを嫌がったということのようです。 この本には、「なぜC++は××に関してこのような仕様になっているのか?」 についての回答が得られる貴重な本です。 余裕があれば読んでみると良いでしょう(分厚いけどね)。 C++の設計と進化 (単行本) ビョーン ストラウストラップ (著), Bjarne Stroustrup (原著), 岩谷 宏 (翻訳), エピステーメ (著) http://amazon.jp/dp/4797328541

Interest
質問者

お礼

回答ありがとうございます。 ご紹介いただいた本、魅力的なのですが分厚いのはやや難ですね。購入するにしても今参考にしている「独習C++」(やっぱり分厚い)をやっつけてからになりそうです。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (4)

回答No.5

クラスと構造体の(実装ではなく)理念上の違いはご理解されているということで良いかと思います。 その上で、「構造体」とは、あくまでもまとまったデータセットです。 このデータセットを「安全に」初期化するためには、コンストラクタというのは、十分に実用的です。 特に、構造体の初期化データを外部から持ってきたり、外部に(暗黙のうちに)保存したりという操作を行うためには、コンストラクタやデストラクタは必須の機能になります。 また、データ特有の操作についても、メンバ関数は有用です。 「クラスでできることをわざわざ構造体でもできるようにした」のは、本来の意味からすれば、クラスと構造体は、別の用途であるので、それぞれの用途に於いて、「統一的に」初期化や後始末や、そのほかの処理が行えるようにしたというところです。

参考URL:
http://www.cmagazine.jp/src/kinjite/cpp/idea.html#index32
Interest
質問者

お礼

回答ありがとうございます。 > このデータセットを「安全に」初期化するためには、コンストラクタというのは、十分に実用的です。 これは大いに頷けます。

全文を見る
すると、全ての回答が全文表示されます。
回答No.4

No.1 の方の回答のとおり、互換性のためだと思います。 既存のCのソースコードに「一切手を入れずに」、修正したり拡張したりする、ということがC++言語仕様策定の重要な要件(作者の)だったと思います。 C++作者の「プログラミング言語C++」(今は第3版?)等を読むと、作者の思いなども書かれていて、とても面白いですよ。 私の独断ではありますが、今では単なる syntax sugar に過ぎなくなっているので、struct の構文は要らないです。 私自身は、すべて class で記述しているので。 ただ、既存の(昔作られた)ライブラリなどをコンパイルするためにはいきなり無くなってしまうと困る、皆様そんなかんじではないでしょうか。 MFCなどを考えて見ると、CPoint等、簡単なものについてはわざわざstructにしてますが、最初うっかりやってしまった後の互換性のため、やむを得ず、ということだと思います。 本質的には全くどうでも良いと思ってます。 > それなら、structに手を加えずそのままにして置けばよかったのに、 > と思うのは私がCばかり使ってきたからでしょうか。 確かに、struct にはメンバ関数は定義できないようにしたうえで、C++としての拡張をしても良かったのかも知れませんね。 ただ。 初期C++言語はCのプリプロセッサとして実装されていたそうで、たぶんコンパイラの実装のことまで考えて妥協した部分もあるのでは? コンパイラの作成は難しいですし。 > 学生時代にC++を勉強したとき使っていた本(※)にそのような記述が無かったような気がします。 > ※柴田望洋著:プログラミング講義C++、ソフトバンクブックス、1997 私も実はそれを読みました(^^; 今は捨ててしまったので確認できませんが、struct と class の関係については、最初から変わっていないと思います。 ので、その本でもウソは書かれていなかったと思うのですが、とにかく、帯に書かれていた宣伝文句とは裏腹に、分りにくい本だったという記憶があります。

Interest
質問者

お礼

回答ありがとうございます。 互換性、の一言に尽きそうですね。 互換性を考えなくて済むJavaでは構造体がなくなっているところを見ると、クラスがあれば構造体が無くても済んでしまうということなのでしょう。 (なのに、C#ではまた構造体が登場して訳が分かりません。) >> ※柴田望洋著:プログラミング講義C++、ソフトバンクブックス、1997 > 今は捨ててしまったので確認できませんが、struct と class の関係については、最初から変わっていないと思います。 本を引っ張り出してきて確認してみたところ、 Column 12-4 クラスと構造体と共用体 に、「(3)メンバ関数を持つことが出来ない」とはっきり書かれていました。 しかし、この本が発行されたのは1996年12月と古いため、ANSI/ISOで標準化されるうちに新しい機能として追加されたのではないかと思っています。

全文を見る
すると、全ての回答が全文表示されます。
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.2

C++では、構造体や共用体もクラスの一種です。クラスなのだから、メンバ関数を持てるのは当然です。 C++のクラスの宣言は、 クラスキー タグ名 という形式で行いますが、このクラスキーに指定できるのは、class, struct, unionの3種類があります。classとstructの違いは、アクセス指定がデフォルトでprivateになるかpublicになるかだけです。unionはメンバ変数のメモリ配置が違ったり、他のクラスから派生したり、派生されたりしない点が大きく異なります。 > クラスでできることをわざわざ構造体(や共用体)でも出来る必要性を感じません。 そういう観点からすれば、structでできるのにわざわざclassを導入する必要はなかったともいえます。

Interest
質問者

お礼

早速の回答ありがとうございます。 > C++では、構造体や共用体もクラスの一種です。 クラスが先にあるのでか。そうなると、CとC++では名前はおなじ struct でも概念は別物(だけどCと同じ使い方はできるようにしてある)と理解しておいたほうがよさそうですね。

全文を見る
すると、全ての回答が全文表示されます。
noname#38837
noname#38837
回答No.1

c互換のためっていうのが一番大きいと思います structを捨てることはできなかったんでしょう 私はclassと構造体は使い分けてますけどね (私は、というより今のプロジェクトがそうなっているからともいえる) http://oshiete1.goo.ne.jp/kotaeru.php3?q=2007539

Interest
質問者

お礼

回答ありがとうございます。 > structを捨てることはできなかったんでしょう それなら、structに手を加えずそのままにして置けばよかったのに、と思うのは私がCばかり使ってきたからでしょうか。 > 私はclassと構造体は使い分けてますけどね 私は  クラス = データと振る舞いをセットにしたもの  構造体 = (関連の深い)データのまとまり と理解していたので、構造体が振る舞いをもったり、継承されたりするとすごく気持ち悪いです。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 構造体のメンバ初期化について

    構造体のメンバを初期化したいのですが、 メンバ数が多いので1個ずつ初期化するのは面倒です。 そのため、一度に初期化する方法を探していたのですが、 memsetやZeroMemoryなどで可能だということが解りました。 しかし、パディング等の問題を含めて この関数を使用しても問題ないのでしょうか? 以下に例を挙げます。 typedef struct SAMPLE {  char a;  int b;  int c;  float d;  SAMPLE(){   ZeroMemory( this, sizeof(Sample) );  } } Sample; 構造体Sampleは32bitマシンでは 一見13byteに見えますが、パディングが入るので、 実際にはsizeof(Sample)は16byteと表示されます。 また、構造体には自動的に初期化と解放するための、 コンストラクタ・デストラクタのみがあり、 関数や仮想関数などの実装はありません。 この方法の安全性について、 ご存知の方がいらっしゃればアドバイスいただけると助かります。 よろしくおねがいします

  • C言語等での画像処理の勉強方法

    画像処理をしたいがためにCを勉強中のものです。 新版 明解C言語 入門編 (単行本) 柴田望洋 (著) を読んでCの基礎を学んだのですが、画像処理については一切触れらていませんでした。 これからC言語で画像処理の勉強をするに当たって分かりやすい本やサイトがあれば教えてください。

  • C++/CLIの構造体のコンストラクタについて

    C++/CLIの構造体のコンストラクタについて C++/CLIで、固定サイズの配列を持つ構造体を、次のようにコーディングして使っています。 value struct AAA { public:   array<unsigned short>^ m1;   AAA(unsigned short dummy)   {     m1 = gcnew array<unsigned short>(4);   } }; AAA ^struct0 = gcnew AAA(0); この方法で正常に動作するのですが、2点ほど気になる点があります。 (1) コンストラクタAAA(unsigned short dummy)を実装しなくても済む方法がないか? (2) この方法では、struct0を、ネイティブヒープ領域に割り当てられない (AAA *struct0 = new AAA(0))でコンパイルエラー) (1)と(2)は関連する気もするのですが、これらを解決する方法はあるのでしょうか?

  • Cで関数とポインタと構造体の表現法

    C言語の関数で 構造体・共用体の入った配列を関数にポインタで送りたいと思うのですが上手くいきません プロトタイプ宣言とメイン文での表現・関数そのものでの表現 が詳しく知りたいのですがサイトまたは記述方を教えてください。 上記の条件で ポインタは*をつけるつけない 関数で引数はどうやって選ぶのか 構造体名などはどのように表現すればいいのか などの見分けがいまいちつかないので悩んでいます。

  • C#の構造体に関して

    C#の構造体に関して C#で構造体で配列を持ちたいと思い、宣言の仕方や使い方を 勉強していますが、どうしてもコンパイルは通るもののエラーと なってしまいます。 《ソース》 単純に構造体で宣言した"a"という配列に、"ABC"という文字列を 代入したいだけですが。。。 namespace テスト環境 { struct test { public string []a; } class Program { static void Main(string[] args) { test aaa = new test(); aaa.a[0] = "ABC"; } } } 配列の初期化等は、ようやく理解したつもりではいますが、構造体 が絡むとどうしてもわかりません。 どこをどのように修正したら良いかを教えて下さい。 初歩的な質問で申し訳ありませんが、よろしくお願いします。

  • 構造体について

    プログラムを勉強し始めて3日目の初心者なんですが、構造体を使う意味がいまいちよくわかりません。 たとえば、構造体の定義が { 縦の長さ 横の長さ 重さ } だとしたら、それを使うためにも { 縦の長さ= a 横の長さ= b 重さ= c } と同じものを2回書く必要があり、なんだか冗長な感じがしてしまいます。 それとも、定義で決めたデータをわかりやすく、間違えないようにするためですか? 本当に未熟で仕組みや使い方もわからない自分の質問なのですが、答えていただければうれしいです。

  • C言語が学びやすいおススメの問題集を教えてください。

    C言語を問題を解きながら実践形式で覚えたいと思っています。 今の僕のレベルは、基本的な参考書を1冊読んだ程度で、 基本的な部分や簡単な配列などがどうにかできるくらい。ポインタや構造体などは一応読みましたが きちんと理解して使いこなせるかは疑問・・・といった程度です。 自分で探して目をつけた本としては、柴田望洋の「解きながら学ぶC言語」があります。 この本はどうでしょうか? その他におススメの本はないでしょうか? ぜひ教えてください。

  • C言語の構造体について

    構造体を勉強している所なのですが変数をまとめられるのは分かりましたがどのサイトを見てもいまいち使い所がわかりません。 struct test { int a; int b; int c; }testtest; testtest.a = 0; testtest.b = 1; testtest.c = 2; 例えば上記のような構造体を作成するとします。 私の見たサイトでは構造体で宣言はまとめられても初期化する事はできないと書いてありました。 下記のように変数を普通に宣言&初期化するよりも手間がかかってしまっていると思うのですが私の考えが及ばない何か別の使い方または処理が早くなったりする事があるのでしょうか?。 int a = 0; int b = 1; int c = 2;

  • javaの二冊目の本

    こんにちは。 現在javaを勉強している新社会人です。 現在使っている「明解java入門編(柴田望洋 著)」がもう少しで終わるので、 次に勉強する本を探しています。 そこで、2冊目のjavaの参考書でお勧めのものがありましたら、 教えていただけないでしょうか。 よろしくお願いいたします。

  • 構造体を引数で関数へ渡す

    こんばんは。現在C言語を学んでいます。 課題という形で構造体で定義されたデータを関数の引数に当てはめ、データを渡すという処理を行わねばならぬのですが、関数を利用しての構造体の受け渡しが分からず苦戦しております。ご助言頂ければ幸いです。 分かりづらいかとは思いますが下記が私が簡単にですが作ったものとなります。 私の考えている動作プロットとしては 1. 構造体の形式を定義する。 2. 冒頭にて存在する関数を定義 3. main関数内にて構造体に名前を付けて定義し、値を入力より受付 4. do_it_hoge関数に構造体を引数として与え(ここが分からず)関数を呼び出す。 5. 関数内にて引数で受け取った &hoge.a,b,c等を表示するなどしたい。(受け取る方法が分からず) 関数を呼ぶ際にカッコ内に入れるのは構造体の名前のみで良いのでしょうか? (例: do_it_hoge(hoge); のように) また呼び出される関数側の括弧は何を記述するのでしょうか? いつもならint hogehoge, や char hoge, などと宣言しているかと思うのですが。 読みづらく、分かりにくいものかとは思いますが どうぞ宜しくご教授頂ければと思っております。 構造体を触るのが久しぶりだったのでそちらでミスがあるかもしれません。もし何か補足等必要でしたらメッセージ頂ければ返事させていただきたいと思います。 //----------------------------------------------------------------// //構造体HOGEHOGE定義 //----------------------------------------------------------------// typedef struct tagHOGEHOGE { int a,b; int c; }HOGEHOGE; void do_it_hoge();//関数定義。ここでのカッコ内の定義も不明 //----------------------------------------------------------------// // main //----------------------------------------------------------------// void main(){ HOGEHOGE hoge;//hogeをHOGEHOGE利用で定義 scanf("%d,%d",&hoge.a,&hoge.b);//カンマ区切りで代入 scanf("%d",&hoge.c);//数値をhoge.cへ do_it_hoge();//←ここが分からず } //----------------------------------------------------------------// // do_it_hoge 関数。構造体を引数で受け取りたい関数。 //----------------------------------------------------------------// void do_it_hoge(){ // ←括弧内の受け方が分からず // ここでmainで入力された &hoge.aなどを参照して表示したい // 例: printf("hogeA:%d",&hoge.a); } //----------------------------------------------------------------//

FAX-360DL子機の液晶が表示しない
このQ&Aのポイント
  • 相談したいことは通話使用すると子機液晶が表示されない問題であり、日にちを置くと表示する場合があること。
  • お使いの環境はひかり回線である。
  • ブラザー製品についての質問です。
回答を見る

専門家に質問してみよう