この記事は、C++ Advent Calendar 2018 の記事です
前日の記事は@Gacchoさんの「C言語とC++の同時比較リファレンス」でした
次日の記事は@Linus_MKさんの「C++ randomライブラリをクラス内で使う方法」です
折角招待して頂いたので普段は触る機会の無い物でも使って何か作ろうかと無計画にネタを考えていたら
スプラトゥーンとスマブラに時間を奪われ間に合わなかったので以前知った小話を
皆さんはこんな奴みたいな事にならないようにスケジュール管理はしっかりしましょう!
#ちょっとしたおさらい
Qiitaを読んでいるような熟練のC++erの方々ならばとっくにご存知の事かとは思われますが
C++でクラスを表す方法としては、C由来のstructを使う方法と、C++にて追加されたclassを使う方法の二種類が存在します。
C++においてこれらの機能は、アクセス修飾子がデフォルトでpublic
かprivate
かと言う点以外は全く同じ機能を持っています。
//下2つの式の意味は同じ
class test{
public:
test();
int a,b,c;
};
struct test2{
test();
int a,b,c;
};
これらの二つのワードで使い分けるべき点は特に無く、個人の趣向やプロジェクト規約に合わせて使い分けていくのが主でしょう。
#疑問
しかし誰しもそんな事を初めて言われたら、class
とstruct
が何故同じ機能を持っているのかと考えるのではないでしょうか?。
そして大抵その解答として
「Cの互換性を維持しつつ、ついでに
class
とstruct
が機能的に似ていたから合わせたんじゃないのか」
と言った回答に辿り着く事でしょう(もしくは教えてもらうか)
まあ大半の理由はそこに有るでしょうし、そんな事を深堀しても殆ど何も出てこないので皆さんさっさとと他の方向に目を追いやった事かと思います。
かく言う自分も特に深堀せずそっぽを向いて、天より授かりし命を重んじこの人生を全うすべく日々慎ましやかに生活してまいりました。
#classとstructで機能が同じである理由
とまあそんなこんなでclass
とstruct
が同じ機能である理由なんぞ特に考えずぼけーっと日々を過ごしていたのですが、
ある日某なんとかちゃんねるでこんな質問をしている方がいらっしゃいました。
「何でC++のclassとstructは機能がほぼ同一なのにわざわざ2つ残したんだ?Cとの互換維持が目的ならデータのみ持つのはstruct、メンバ関数も含めるのはclassにした方が機能の重複が無くて有意義じゃないか!」
ううむ…確かに一理あるなぁ
Cのstruct
とC++のclass
は多少似ている部分は有れどそれまでの使われ方は異なっていた訳だし
折角class
と言う新しい概念を作ったのであればstruct
と切り離してしまった方が機能がより明確になるし
両方のワードが残っている意味も出来て有意義だったのかなぁ…などと思いながら読み進めていたところ、それに対しての回答があり、
「classとstructが同じ理由 探してみたらC++の設計と進化に書いてあったぞ! 読んでみそ」
とのこと…
C++の設計と進化…そういや以前に2,3回読んで本棚にシュートしたな…と思いつつ本棚へいざ冒険に
荒波乗り越え見事発見し色々と読んでみた所、C++の設計と進化には以下のように書かれていました。
Bjarne Stroustrup著 :「C++の設計と進化」p94-95より引用
…C++の仮想関数のあるクラスのオブジェクトは、Cの単純なstructとは根本的に異なるものである。しかしそれではなぜ、私はこの時点で、structとclassを別の概念にすることを選ばなかったのだろう?
私の意図は、概念を一つにすることだった:レイアウトのルールも一つ、参照のルールも一つ、解決(resolution,名前の解決)のルールも一つにする。ルールを二つにしてもそんなに困らなかったかもしれないが、しかし単一概念の方が、各機能の円滑な結合化と単純な実装を可能にする。structが"Cと互換性"のテーマに属して、classが"C++と高度な機能"に属したら、ユーザグループが二派に分かれ、犬猿の仲になってしまうだろう。
クラスを設計するときは、言語の機能をありったけ使うこともできるし、逆にできるだけ少なめに使うこともできる
…(中略)…その後いろんな人が"クラスだけに"実装できる高価なアイデアを次々と持ち込み、対照的に、structのオーバーヘッドの少ない簡素さが際立った。structとclassを同じ一つの概念でカバーしたことによって、クラスの機能の
過肥大も防げた、と私は信じている。つまり"structはclassである"という概念によって、C++が低レベルのサブセットと絶縁した高級すぎる高級言語に浮揚していくことを防げた、と思うのである。それを望んでいた人もいるだろうが。
要所をざっくりと抜き出すと
-
class
は仮想関数を持った時点でCのstruct
と根本的に違う物になったのになぜ分けなかったのか 理由は以下の通り-
struct
とclass
の概念を一つにしたかった その方が円滑に結合できるし単純実装で済む - もし
struct
とclass
の概念が別々に分かれていたら、各派閥に分かれ犬猿の仲になってたはず
-
-
またこのような選択を取ったことにより、以下の二つの目的が達成された
- 「
struct
はclass
である」と言った概念を定義する事により、class
機能の肥大化を防ぐことが出来た - C++がCに程遠い高級言語と言う位置付けになるのを防ぐことが出来た(望んでた人もいるんだろうけど)
- 「
と言う事でした。
確かにstruct
とclass
で概念が分かれていたらややこしくなるでしょうし、分けた事によりどちらの方が優れているかーなどと言う無駄な議論が起こるぐらいなら
多少くすぐったい所があれど概念は一本化したほうがてっとり早いですね。
#まとめ
という訳で、class
とstruct
が同じ機能を有している事情にはこんな理由があったそうです。
ところで、そんなにclass
とstruct
を同一概念にしたいのであればstruct 一本 にしても良かったのでは?と言う意見も出てきそうな物ですが、全く新しい機能が同一の名前でのみサポートされていては混乱を招きかねませんし、
結局は同一の概念にすると言う選択肢が一番ベストだったのでしょう。
結果的に今些細な疑問が持たれることはあれど激しく非難されるような疑問ではないですし、class
とstruct
の概念を同一にする選択は正しかったのかもしれません。
#補足
ツッコミ、持論、マサカリ等有りましたらどんどん投げてくださると嬉しいです。