こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

構造体とクラスの違い

お世話になります。

先日、C(C++もかな?)のベテランのプログラマの方が「構造体とクラスはまったく違うものだ」ときっぱり言い切っていらっしゃいました。私は、構造体にメソッドが加わったものがクラスだ、くらいな認識で、まったく違うものというよりはかなり近しい概念だと思っていたので少々驚いた次第です。

疑問が残りましたので、インターネットでいろいろ検索してみたのですが、おしなべて「構造体とクラスには共通点が多い」と説明されており、どうしても「まったく違うもの」と解釈できる文献を見つけることができませんでした。

果たして「構造体とクラスはまったく違うもの」なのでしょうか?

投稿日時 - 2006-03-05 01:34:19

QNo.2007539

暇なときに回答ください

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

> オブジェクト指向で大切なのは、プログラム(システム)全体での、各個のクラス
> の役割(機能)と相互機能関係を堅牢に設計すること
> というように解釈してよいでしょうか。また、そういう意味でUMLによる開発が有効
>なのでしょうか。
よく勉強なさっていらっしゃいますね。基本的には、ユーザをよく理解し、正しい文章を起草することが大切ということではないでしょうか。意味不明の文章(仕様書)を書く人が多いと思います。ただし、C++を設計したBjarne Stroustrup氏は、自分はプログラマである、とはっきり立場を表明されているようです(分析と設計、あるいは、度重なる打ち合わせだけではプログラムは完成しません)。

> 自分はJavaからプログラムに入った人間なのですが、
この意味がよく分かりません。

> 逆にJavaはオブジェクト指向を強制する言語ということになるでしょうか。
Stroustrup氏は、SmallTalkやJavaをこのように見ている節があります。
なお、同氏は、Javaは開発者だけではなく、マネージャなどの支持を取り付けようとした、という認識を示しているようです。

> ここでいう「型」の安全性とは、「その型のメンバへの不正アクセス発生の可
> 能性の有無」みたいなことでしょうか。
「型」の安全性を保障するには、ある時点で「型」、および、「型」と「型」の間の関係をチェックする必要があります。このチェックは実行時ではなく、コンパイル時に行うのが理想です。Stroustrup氏は、このような方針を打ち出しました。ちなみに、Cも先行するBなどより「型」を重視する言語です。どのような型がどのようにチェックされるのかを知りたい場合、恐れ入りますが、OSSなどの、たとえば、SQLiteなどを無料のVC++ Express Edition(VCEE)などでビルドしてみてください。VCEEはC++標準仕様を忠実に実装しようとしています。あるソースコードをビルドすると200を越える警告が出されます(そのように型チェックが行われる)。

> これもC++においてということでよろしいでしょうか
> (Javaで設計されたクラスはすべてObjectクラスの子クラスだと思うので)
テンプレートやジェネリック、という概念を後日調査してください。C++の考え方は、JavaやC#などに浸透しています(Stroustrup氏はこの自体をすでに予言していました)。

参考になれば幸いです。

投稿日時 - 2006-03-05 15:53:30

ANo.11

このQ&Aは役に立ちましたか?

21人が「このQ&Aが役に立った」と投票しています

回答(15)

ANo.15

ちなみにC言語では、構造体とクラスはまったく別物です。
構造体については説明するまでもありませんが、C言語におけるクラスとは「記憶クラス」のことで、extern, static, register, autoといった記憶クラス指定子を付けることで指定できるものです(typedefも記憶クラス指定子ですが、それはあくまでも構文上のものです)。

単に「クラス」といっても、具体的に何のことをいっているのかよく確認した方がよいでしょう。オブジェクト指向におけるクラスとC++のクラスは必ずしも等価ではありませんし、上で書いたように、また別の意味でのクラスであれば当然意味が違ってきます。

投稿日時 - 2006-03-06 18:03:16

ANo.14

C++の文法上は、「構造体とクラスは、アクセス制御の初期値が異なる点を除いて同一のもの」です。
これは、「C++の実装」の話。

オブジェクト指向においては、クラスは、「自律的な動作を行うひとまとまりの単位」です。
C++では、たまたま、構造体の文法で実装したに過ぎません。

例えば、下記の ULR をご参照ください。

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

投稿日時 - 2006-03-06 10:15:39

ANo.13

 「構造体とクラスはまったく違うものだ」ではなくて「Cの構造体と C++のクラスはまったく違うものだ」ではないでしょうか。
 C++における構造体とクラスに関しては前の方々が書かれている通り大差なしなのですが、Cの構造体と C++のクラスとなると結構違うものになります。

 たしかにクラスは一見するとコンストラクタやメソッドが使えて、継承ができるといった+α的な役割です。
 しかしだからといって、例えばCの構造体ではインスタンス生成後の領域に対して memsetなどで0クリアすることがよくあると思いますが、C++のクラスで同じことをするのは(非POD型以外では)リスキーな行為です。
(実際うちのプロジェクトで memsetしていた人がいて、クラス内のメンバのあるオブジェクトに仮装関数を実装したらとたんに動かなくなりました)

 そのベテランさんはそういった意味で Cは得意だけどC++に不慣れな人に向けて「同じだと思って扱うな」ということが言いたかったのではないでしょうか。

投稿日時 - 2006-03-05 18:58:51

ANo.12

nk2

Cでいう構造体をC++で表現すると
その型名をC++ではPOD型というんですよ。

struct plain_old_data_struct
{
int a,b,c;
char a,b;
};

class plain_old_data_class
{
public:
int a,b,c;
char a,b;
}

上のどちらもPOD型です。
恐らくそのベテランのプログラマさんは
CとC++で構造体の定義が異なることを知らなかったのでしょう。

ただ私もそうですがPOD型をclassで宣言することはありません。
C++ISO仕様でclassとstructはデフォルトアクセスレベルの違いでしかないので、私はPOD型をstructで、それ以外をclassで表現しています。

私のように使い分けると、
structはデータ集合(POD)、classはモジュールを示すようになります。
当然、データ集合(POD)とモジュールとはまったく違う物ですよね。

投稿日時 - 2006-03-05 17:13:12

ANo.10

> オブジェクト指向と手続き指向はまったく違うプログラミング作法だということを
> 強調したいということでしょうか。
なんともいえないところですが、次の3点は覚えておいて損にならないと思います。

・C++はオブジェクト指向を強制したりしない!
・C++は「型」の安全性が保証される限り、Cを継承する!
・すべてのクラスが何らかのオブジェクト階層に属するわけではない!

「オブジェクト指向と手続き指向」という用語がよく使われますが、忘れるべき用語です。クラスを構成するメソッド(メンバー関数)の実装では、"手続き指向"が一般的です。オブジェクト指向で大切なのは、クラスの設計と階層設計(Simula)であり、実装面では手続き指向(C)です。C++は、SimulaとCの融合の結晶です。Javaや.NETは、Simulaと仮想マシン(Cの抽象化環境)の融合です。

投稿日時 - 2006-03-05 11:59:12

お礼

詳しいご説明をどうもありがとうございます。

> オブジェクト指向で大切なのは、クラスの設計と階層設計(Simula)であり

これは、

オブジェクト指向で大切なのは、プログラム(システム)全体での、各個のクラスの役割(機能)と相互機能関係を堅牢に設計すること

というように解釈してよいでしょうか。また、そういう意味でUMLによる開発が有効なのでしょうか。

とても勉強になるので、もう少しお尋ねしたいと思います。

自分はJavaからプログラムに入った人間なのですが、

> ・C++はオブジェクト指向を強制したりしない!

に対して、逆にJavaはオブジェクト指向を強制する言語ということになるでしょうか。

> ・C++は「型」の安全性が保証される限り、Cを継承する!

ここでいう「型」の安全性とは、「その型のメンバへの不正アクセス発生の可能性の有無」みたいなことでしょうか。

> ・すべてのクラスが何らかのオブジェクト階層に属するわけではない!

これもC++においてということでよろしいでしょうか(Javaで設計されたクラスはすべてObjectクラスの子クラスだと思うので)。

投稿日時 - 2006-03-05 12:43:59

ANo.9

クラスにはclassとstructとunionとenumが含まれます。
よって、classとstructは別物ですが
構造体はクラスの一部です。

投稿日時 - 2006-03-05 10:47:57

お礼

ありがとうございました。構造体は必ずクラスだが、クラスは必ずしも構造体ではない、ということになるでしょうか。

投稿日時 - 2006-03-05 11:44:39

ANo.8

がると申します。
まぁ色々な方が的確な回答をつけられているので蛇足になるのですが。
実装の側面から考えると、クラスは、質問者さんのおっしゃるとおり、「構造体+関数」程度のものになります(実際にはもうちょっとだけ余分にいくつかつきますが、主だったところでは)。
ただ、「クラス」、或いはその背景にある「オブジェクト指向」の理論側面から考えると、クラスと構造体は大分違うものになります。
いやまぁ「データを塊として扱う構造体に+α」っていう意味ではYesなのですが、クラスという発想はその+αに大きな比重があるので。

ですので、多分その「+α」に目を向けて欲しいという意味で、あえてまったく違う、という言い方をしたのかなぁ? とか推測してみました。

投稿日時 - 2006-03-05 10:43:58

お礼

ありがとうございます。

> ですので、多分その「+α」に目を向けて欲しいという意味で、
> あえてまったく違う、という言い方をしたのかなぁ? とか推測してみました。

ひょっとしたらそういう意図だったのかもしれないなとも思いました。

> いやまぁ「データを塊として扱う構造体に+α」っていう意味ではYesなのですが、
> クラスという発想はその+αに大きな比重があるので。

+αというのは、多態性や継承とかですよね。あるとなしではえらい違いですものね。というかそれがオブジェクト指向の核ですものね。

投稿日時 - 2006-03-05 11:42:39

ANo.7

> 疑問が残りましたので、インターネットでいろいろ検索してみたのですが、
> おしなべて「構造体とクラスには共通点が多い」と説明されており...
構造体もクラスも(ユーザ定義)「型」という範疇に入る点では多くの共通点を持っています。C++設計者のBjarne Stroustrup氏は、「class」という名称のキーワードを採用する際、「type」という名称でもよいと考えたようでした。しかし、「type」という新しいキーワードを使用すると開発者が新たなキーワードを覚える必要があり、その負担へ配慮し、従来から存在する「class」を採用しました。

構造体とクラスの間には多くの共通点があります。しかし、それらを使用する際には、データの構造化ではなく、オブジェクトの「資源管理」や「状態管理」という概念を理解する必要があります。たいへん残念なのですが、この当たりの本質的な議論はわが国ではほとんど見られません。

Stroustrup氏は、C++を学ぶためにCを学ぶ必要はない、C++をC的に理解することは好ましいことではない、と繰り返し述べています。構造体は、Cからの借り物であり、C++独自のものでもありません。C++に「抽象クラス」を追加するまでに数年かかっています。具象クラスや抽象クラス、あるいは、例外などを調査してみてください。

参考URL:http://www.ttoyota.com/php/cppintro.php

投稿日時 - 2006-03-05 09:57:59

お礼

ありがとうございます。

> Stroustrup氏は、C++を学ぶためにCを学ぶ必要はない、
> C++をC的に理解することは好ましいことではない、と
> 繰り返し述べています。

という言葉はとても印象的です。オブジェクト指向と手続き指向はまったく違うプログラミング作法だということを強調したいということでしょうか。

また、オブジェクトの「資源管理」や「状態管理」などについても追々勉強していきたいと思います。

投稿日時 - 2006-03-05 11:36:15

ANo.6

標準C++における規格上の定義は次の通りです。
「JIS X3014:2003 9.クラス」の4より

---引用ここから---
構造体は、<<クラスキー>>structを付けて定義するクラスとする。そのメンバ及び基底クラスは、特に指定がない限り公開となる。
---引用ここまで---

つまり、全く違うものではなく、構造体はクラスの一種です。

ただし、ローカルなルールで、構造体とクラス(正確にはstructとclass)を異なる用法に制限している可能性はあります(#5と同じ)。
そうした観点からすれば、intとsigned intであっても、全く違うものになりえます(実際に、ビットフィールドではこれらの型は意味が異なります)。

ちなみに、標準ライブラリでも、std::char_traitsなどはメンバ関数をもっていてもstructです。公開メンバしか持たない場合には、メンバ関数があってもstructにするのは普通のことです。

投稿日時 - 2006-03-05 08:01:35

お礼

ありがとうございます。標準規格でそのように定められているのなら、やはり「まったく違うものではない」と考えるのが妥当なのだなという認識を持ちました。

投稿日時 - 2006-03-05 11:26:50

ANo.5

↓で「宗教的」と書きましたが、もしかしたら特定の組織のコーディング規則ということもあるかもしれません。もし、そのベテランプログラマの方が「われわれのコーディング規則では構造体とクラスは全く違うものとして扱うことになっている」という意味で言っておられたのなら、妥当な意見です。私もそうしています。「struct は c++の使えない環境でもそのまま動くことが保証された特別な書き方をした class とする」というコーディング規則は非常に有用ですから。

投稿日時 - 2006-03-05 07:28:24

お礼

ありがとうございます。実際のコーディングのフェーズでそういった規則を定めて製造を行うというのは至極まっとうなことだと思いますが、そのときは原則論的な話だったので、疑問を持った次第であります。

投稿日時 - 2006-03-05 11:17:49

ANo.4

その、ベテランプログラマの方にはなんらかの宗教的な信念がおありでそのようなことを言っておられると思います。

基本的に class と struct は private か public かの状態が class ではディフォルトが private、struct では public になっているというだけしか違いはありません。メンバーを宣言するときに必ず public とか private からはじめるようにすれば class と struct は入れ替え可能です。

とはいえ、私自身 struct を使うのは c 文法でしか使わないものにしか使いません。struct でメンバ関数とか継承を使うのは、かなり「変わった書き方」という印象を与えますから。しかし、文法的には問題ないと思います。

ですからといって「まったく違うものだ」というのは、宗教的な信念であるとしか思えません。

投稿日時 - 2006-03-05 07:14:09

ANo.3

著者へC++言語を作った人→著者の一人はC++言語の設計者

投稿日時 - 2006-03-05 03:41:41

ANo.2

The Annotated Reference Manual
「注解C++リファレンスマニュアル」(初版)
によると
構造体,デフォルトのアクセス制限の存在しないクラス
とありますので、(著者へC++言語を作った人)
C++においては、
構造体は、クラスの特別な形のもの
という認識でいいと思います。

投稿日時 - 2006-03-05 03:37:41

お礼

ありがとうございます。クラスとは、構造体の構成要素(メンバ)及び構造体自身に可視性を定義できることにより、オブジェクトとしての(型としての?)安全性を高めた構造体とも言えるということでしょうかね。

投稿日時 - 2006-03-05 11:13:20

ANo.1

クラスの概念を実装するのに構造体を利用した、というのだと思います。構造体+メソッドとして関数などを追加していますよね。実際、クラスの概念には他に継承や多態性などもありますので、構造体とクラスがかならずしも共通点が多いという事ではないです。
まあ、構造体をクラスであらわす事ができるのでそういう考え方もありますが、オブジェクト指向としてクラスという概念を考えると違う点もあります。また、プログラム的に考えたとしても参照渡しか値渡しかという違いもありますね。

投稿日時 - 2006-03-05 02:56:53

お礼

ありがとうございました。Cにおける構造体はabstract宣言できないんですよね。そういう点でクラスと構造体は違うなあということはよく理解できます。

投稿日時 - 2006-03-05 11:05:35

あなたにオススメの質問