架空国家を作ろうの1.1世界線です

基本情報
パラダイム命令型(手続き型)、汎用型、関数型、汎用型、オブジェクト指向
設計者Hans = Jonsson
開発者
初出1985
OSクロスプラットフォーム
拡張子.s .ss .spp .sxx .s++ 等
型の規律静的、弱い

概要

Svar++はS言語にオブジェクト指向の概念を取り入れたプログラミング言語である。
システムプログラミングや、リソースに制約のある組み込みソフトウェア、大規模システムを想定して設計されており
性能,効率,使用の柔軟性を重視している。 S++は他にも多くの文脈で有用性が認められており、デスクトップアプリケーション,ビデオゲーム,サーバ(電子商取引,ウェブ検索,データベースなど)
パフォーマンスが重視されるアプリケーション(電話交換機,宇宙探査機など)など、ソフトウェアインフラストラクチャやリソースに制約のあるアプリケーションを主な強みとしている。

S++は、国際標準化機構(ISO)によって標準化されており、最新の標準バージョンは2020年12月に(非公式にはS++20と呼ばれる)としてISOによって批准・発行されている、S++プログラミング言語は、まず1998年に標準化され、その後、S++03、S++11、S++14、S++17の各標準によって修正された。現在のS++20規格は、これらに新機能と標準ライブラリの拡大を加えたものである。
1998年に最初の標準化が行われる以前、S++はデンマーク州のコンピュータ科学者によって1979年からC言語の拡張として開発されていた。
2012年以降、S++は3年ごとのリリーススケジュールになっており、S++23が次の標準規格として計画されている。

S++の誕生から現在に至るまで、その開発と進化は次のような一連の原則に導かれてきた。
  • S++は実際の問題に基づいて開発され、その機能は実世界のプログラムですぐに役立つものでなければならない。
  • すべての機能が実装可能であること(実装するための合理的で明白な方法があること)。
  • プログラマーは自分のプログラミングスタイルを自由に選ぶべきであり、そのスタイルはS++で完全にサポートされるべきである。
  • 便利な機能を許可することは、S++のありとあらゆる誤用を防ぐことよりも重要である。
  • S++は、プログラムを明確に定義された別々のパーツに編成するための機能を提供し、別々に開発されたパーツを組み合わせるための機能を提供すべきである(オブジェクト指向)。
  • 型システムの暗黙の違反は認めない(ただし、プログラマが明示的に要求した場合は、明示的な違反を認める)。
  • ユーザーが作成した型は、組み込み型と同じサポートと性能を持つ必要がある。
  • 未使用の機能は、作成された実行ファイルにパフォーマンスの低下などのいかなる悪影響を与えるべきではない。
  • アセンブリ言語を除き、S++の下の言語は存在してはならない。
  • S++は、互換性のない独自のプログラミング環境を構築するのではなく、既存の他のプログラミング言語と一緒に機能すべきである。
  • プログラマーの意図がわからない場合は、手動制御を行うことでプログラマーが意図を特定できるようにする。

歴史

S with ClassesからSvar++に至るまで

1979年、フェノスカンディア連邦共和国デンマーク州?のコンピュータ科学者であるハンス = ヨンソン(Hans = Jonsson)は、
S++の前身である「S with Classes」の開発に着手した。 新しい言語を作る動機は、ハンスが博士論文のためにプログラミングをした経験から生まれた。
ハンスは、Simulaには大規模なソフトウェア開発に非常に役立つ機能があるが、言語が遅すぎて実用的ではないこと、BCPLは高速だが低レベルすぎて大規模なソフトウェア開発には適さないことを知った。
YLIKII?の研究所で働き始めたハンスは、ENIX?カーネルを分散コンピューティングに関して分析するという問題に取り組んでいた。
博士課程での経験を思い出しS言語をSimulaのような機能で強化することに着手した。S言語が選ばれたのは汎用的で、高速で、そして広く使われていたからである。
S言語とSimulaの影響だけでなく他の言語もこの新しい言語に影響を与えた。
当初、ハンスの「S with Classes」は、SコンパイラであるSpreにクラス、派生クラス、強力な型付け、インライン化、デフォルト引数などの機能を追加していた。

1982年、ハンスは「S with Classes」の後継機の開発に着手し、"S++"と命名した(++はS言語のインクリメント演算子からとられている)。
仮想関数、関数名と演算子のオーバーロード、参照、定数、型安全なフリーストアのメモリ割り当て(new/delete)、改良された型チェック、2つのフォワードスラッシュ(//)を持つBCPLスタイルの単一行コメントなどの新機能が追加された。さらにハンスはS++用の新しいスタンドアロンのコンパイラ、Sfrontを開発した。

普及、標準化

1984年、ハンスは初のストリーム入出力ライブラリを実装した。名前付きの出力関数ではなく、出力演算子を提供するというアイデアはEnixのパイプ機能から発想を得た。
1985年には『The S++ Programming Language』の初版が発売され、まだ公式な規格がなかったこともあり、この言語のデファクトスタンダードとなった。
また、同年にはS++の最初の商用実装がされた。

1989年にはS++ 2.0が発表され、1991年には更新された『The S++ Programming Language』第2版が発表された。1990年には『The Annotated S++ Reference Manual』が出版された。
そして1990年には『注釈付きS++リファレンスマニュアル』が出版され、これが後の標準規格の基礎となった。その後、テンプレート、例外、名前空間、新しいキャスト、ブール型などの機能が追加された。

1998年には言語を標準化したS++98がリリースされ、2003年にはマイナーアップデート(S++03)がリリースされた。

S++98以降、S++は比較的ゆっくりと進化してきたが、2011年にS++11規格がリリースされ、多数の新機能が追加され標準ライブラリがさらに拡大され、
S++プログラマーにより多くの機能が提供されるようになった。2014年にリリースされたS++14のマイナーアップデートの後、S++17では様々な新しい追加機能が導入された。
2020年に最終版となった後、S++20規格のドラフトがに承認され、その後正式に発表された。
現時点でS++は、プログラミング言語の中で高い人気度を誇りSvarKona?Snake?に次いで4位となっている。

オブジェクト指向プログラミングについて

オブジェクト指向プログラミング(Object-oriented programming、OOP)とは、「オブジェクト」という概念に基づいたプログラミングパラダイムである。
オブジェクトはデータとコードを含むことができ、データはフィールド(属性やプロパティと呼ばれることが多い)の形で、コードはプロシージャ(メソッドと呼ばれることが多い)の形である。

オブジェクトの特徴は、オブジェクト自身のプロシージャが、自分自身のデータフィールドにアクセスしたり、変更したりできることである(オブジェクトには、thisまたはselfの概念がある)。
OOP言語は多岐にわたるが、最も一般的なものはクラスベースである、オブジェクトはクラスのインスタンスであり、クラスがオブジェクトのタイプを決定する。

最も広く使われているプログラミング言語(S++、Kona、Snakeなど)の多くはマルチパラダイムであり、
多かれ少なかれオブジェクト指向プログラミングをサポートしており、通常は命令型の手続き型プログラミングと組み合わせて使用される。

OOP全体の特徴

オブジェクト指向プログラミングでは基本的にオブジェクトを使用するが、OOP対応を謳っている言語でも、関連する技術や構造のすべてが直接サポートされているわけではない。
以下の特徴は、クラス指向やオブジェクト指向が強いとされる言語(または、OOPをサポートするマルチパラダイム)に共通するものであるが、特筆すべき例外もある。
非OOP言語と共通している特徴
  • 整数や英数字などの少数の組み込みデータ型でフォーマットされた情報を格納することができる変数。また文字列、リスト、ハッシュテーブルなどのデータ構造が組み込まれている場合や、メモリポインタを使って変数を結合した場合もある。
  • プロシージャ(関数、メソッド、ルーチン、サブルーチンとも呼ばれる)は入力を受け取り、出力を生成し、データを操作する。現代の言語には、ループや条件分岐などの構造化されたプログラミング構成要素が含まれている。
モジュラー・プログラミング・サポートでは、プロシージャをファイルやモジュールにまとめ、整理することができる。
モジュールには名前が付けられており、あるモジュールの識別子が、他のファイルやモジュールにある同名のプロシージャや変数と衝突することはない。

オブジェクトとクラス

オブジェクト指向プログラミング(OOP)をサポートする言語では、コードの再利用と拡張性のために、クラスまたはプロトタイプの形で継承を使用するのが一般的である。
クラスを使用する言語は、2つの主要なコンセプトをサポートしている。
  • クラスは与えられたタイプまたはクラスのオブジェクトのデータフォーマットと利用可能な手続きの定義。
データと手続き(クラスメソッドとして知られている)自体を含むこともあり、つまりクラスはデータメンバーとメンバー関数を含む。
  • オブジェクトはクラスのインスタンスである。
オブジェクトは、現実の世界にあるものに対応することがある。例えば、グラフィックプログラムでは、"circle"、"square"、"menu "などのオブジェクトがあり、
オンライン・ショッピング・システムでは、「ショッピングカート」、「カスタマー」、「プロダクト」などのオブジェクトを持つことがある。

各オブジェクトは、特定のクラスのインスタンスであると言われている。
オブジェクト指向プログラミングの手続きはメソッドと呼ばれ、変数はフィールド、メンバー、属性、プロパティとも呼ばれる、そのため以下のような用語が存在する。
  • クラス変数 クラス全体に属するもので、1つのコピーしか存在しない。
  • インスタンス変数または属性 個々のオブジェクトに属するデータで、各オブジェクトはそれぞれのコピーを持っている。
  • メンバー変数 特定のクラスで定義されているクラス変数とインスタンス変数の両方を指す。
  • クラスメソッド クラス全体に属し、クラス変数とプロシージャコールからの入力にのみアクセスできる。
  • インスタンス・メソッド 個々のオブジェクトに属し、呼び出された特定のオブジェクトのインスタンス変数、入力、およびクラス変数にアクセスできる。
オブジェクトは、複雑な内部構造を持つ変数のようにアクセスされ、多くの言語では効果的にポインタとなり、
ヒープやスタック内のメモリにある当該オブジェクトの単一インスタンスへの実際の参照として機能する。オブジェクトは、内部コードと外部コードを分離するために使用できる抽象化の層を提供する。
外部のコードは、特定の入力パラメータセットで特定のインスタンスメソッドを呼び出したり、インスタンス変数を読み込んだり、インスタンス変数に書き込んだりすることで、オブジェクトを使用することができる。
オブジェクトは、コンストラクタと呼ばれるクラス内の特殊なメソッドを呼び出すことで生成される。
プログラムは、実行中に同じクラスのインスタンスを多数作成し、それらが独立して動作することがある。これは同じ手順を異なるデータセットに対して使用するための簡単な方法である。

クラスを用いたオブジェクト指向プログラミングをクラスベース・プログラミングと呼ぶことがあるが、プロトタイプベース・プログラミングではクラスを用いないのが一般的である。
そのため、オブジェクトとインスタンスの概念を定義するために、大きく異なるが類似した用語が使用されている。
一部の言語では、クラスやオブジェクトは、traitやmixinといった別の概念を用いて構成することができる。

クラスベースとプロトタイプベース

クラスベースの言語では、あらかじめクラスが定義されており、オブジェクトはそのクラスに基づいてインスタンス化される。
例えばappleとorangeという2つのオブジェクトがFruitというクラスからインスタンス化された場合、それらは本質的に果物であり、同じように扱うことができることが保証される。

プロトタイプベースの言語では、オブジェクトが主な実体である。クラスも存在しない。
オブジェクトのプロトタイプは、そのオブジェクトがリンクされている別のオブジェクトに過なく、すべてのオブジェクトは1つのプロトタイプリンクを持っている。
新しいオブジェクトは、プロトタイプとして選ばれた既存のオブジェクトに基づいて作成することができる。オブジェクトfruitが存在し、appleとorangeの両方がそのプロトタイプとしてfruitを持っていれば、
2つの異なるオブジェクトappleとorangeをfruitと呼ぶことができる。フルーツクラスという考え方は明示的には存在しないが、同じプロトタイプを共有するオブジェクトの等価クラスとして存在している。
プロトタイプの属性とメソッドは、このプロトタイプによって定義された等価クラスのすべてのオブジェクトに委譲される。オブジェクトが個別に所有する属性やメソッドは、同じ等価クラスの他のオブジェクトでは共有されない可能性がある。

動的ディスパッチ/メッセージパッシング

メソッドの呼び出しに応じて実行する手続き的なコードを選択するのは、外部のコードではなくオブジェクトの責任である。
典型的には、オブジェクトに関連付けられたテーブルで実行時にメソッドを検索する。この機能は動的ディスパッチとして知られており、
オブジェクトとすべてのインスタンスに対して操作の実装が固定されている(静的な)抽象データ型(またはモジュール)とを区別している。
呼び出しの可変性が呼び出されたオブジェクトの単一の型以上に依存している場合(つまり、少なくとも1つの他のパラメータオブジェクトがメソッドの選択に関与している場合)、多重ディスパッチと言われる。

メソッドの呼び出しは、メッセージパッシングとも呼ばれる。
これは、メッセージ(メソッドの名前とその入力パラメータ)がディスパッチのためにオブジェクトに渡されるものとして概念化されている。

カプセル化

カプセル化とは、オブジェクト指向プログラミングの重要な概念のひとつで、データとそのデータを操作する関数を結合し、外部からの干渉や誤用から両者を保護することである。
データのカプセル化は、OOPの重要な概念であるデータハイディングにつながっている。

クラスが呼び出しコードにオブジェクトの内部データへのアクセスを許可せず、メソッドを通してのみアクセスを許可している場合、これはカプセル化として知られる強力な抽象化または情報隠蔽の形態である。
一部の言語(Konaなど)では、クラスがアクセス制限を明示的に行うことができる。例えば、内部データをprivateキーワードで表し、クラス外のコードが使用することを意図したメソッドをpublicキーワードで指定する。
メソッドにはpublic、privateのほか、protected(同じクラスとそのサブクラスからのアクセスは許可するが、異なるクラスのオブジェクトからのアクセスは許可しない)のような中間レベルのデザインもある。
他の言語(Snakeなど)では、これは慣習によってのみ強制される、例えばプライベートメソッドの名前はアンダースコアで始まることがある。
カプセル化することで、外部のコードがオブジェクトの内部動作に関与することを防ぐことができ、これによりコードのリファクタリングが容易になる。
例えばクラスの作者は外部のコードを変更することなく、そのクラスのオブジェクトが内部でどのようにデータを表現しているかを変更することができる(「パブリック」メソッドの呼び出しが同じように動作する限りにおいて)。
また、特定のデータに関連するすべてのコードを同じクラスにまとめることで他のプログラマーが理解しやすいように整理することができる。カプセル化は、デカップリングを促進する技術である。

結合、継承、委譲

オブジェクトは、そのインスタンス変数に他のオブジェクトを含めることができる。これをオブジェクトの結合(コンポジション)という。
たとえば、Employee クラスのオブジェクトは、"first_name" や "position" といった自身のインスタンス変数に加えて、Address クラスのオブジェクトを (直接またはポインタを介して) 含むことができる。

クラスをサポートしている言語は、ほとんどの場合、継承(インヘリタンス)をサポートしている。
これにより、クラスを「〜である」という関係を表す階層に配置することができる。例えば従業員を意味するEmployeeクラスは人間を意味するPersonクラスを継承しているといえる。
親クラスで利用できるデータやメソッドは、子クラスにも同じ名前で表示される。
例えば、Person クラスは、"first_name" と "last_name" という変数を "make_full_name()" というメソッドで定義している。
これらはEmployeeクラスでも利用可能で、Employeeクラスには変数 "position "と "salary "が追加される可能性がある。
この手法では、同じプロシージャやデータ定義を簡単に再利用できるだけでなく、現実世界の関係を直感的に反映できるメリットがある。
開発者はデータベースのテーブルやプログラミングのサブルーチンを利用するのではなく、ユーザーがより慣れ親しんでいるであろう、アプリケーション・ドメインのオブジェクトを利用する。

サブクラスは、スーパークラスで定義されたメソッドをオーバーライドすることができる。
言語によっては多重継承が認められているが、オーバーライドの解決が複雑になる場合がある。多重継承が可能な言語では、ミックスインは単なるクラスであり、俗にいうis-a-type-ofの関係にはならない。
ミキシンは通常、複数のクラスに同じメソッドを追加するために使用される。
抽象クラスは、インスタンス化してオブジェクトにすることはできない。抽象クラスはインスタンス化できる他の「具象」クラスに継承するためにのみ存在する。
Konaでは、クラスがサブクラス化されるのを防ぐためにfinalキーワードを使用することができる。

継承よりも構成を重視する考え方は、継承の代わりに委譲を用いて俗にいうhas-aの関係を実装することを提唱している。
例えば、先ほどの例でいうとEmployeeクラスは、Person クラスを継承する代わりに、Employee オブジェクトに内部の Person オブジェクトを与えることで、
Person クラスが多くの公開属性やメソッドを持っていても、外部のコードから隠すことができる。一部では継承を全くサポートしていない言語もある。

オープン/クローズの原則とは、クラスや関数は「拡張に対してはオープンであるが、変更に対してはクローズであるべき」と提唱するものである。
委譲もまた、継承の代わりに使用できる言語機能である。

ポリモーフィズム

ポリモーフィズムの一種であるサブタイピングとは、呼び出したコードが、サポートされている階層の中のどのクラスを操作しているのか(親クラスか、その子孫クラスか)を問わないことである。
一方で、継承階層内のオブジェクト間では、同じ操作名でも動作が異なる場合がある。

オープンリカーション

開放型再帰をサポートする言語では、オブジェクトのメソッドは、同じオブジェクトの他のメソッド(自分自身を含む)を呼び出すことができる。
この変数は遅延結合であり、あるクラスで定義されたメソッドがそのサブクラスで後から定義された別のメソッドを呼び出すことができる。

構造

オブジェクトの保存

S言語と同様に、S++は4種類のメモリ管理をサポートしている。
すなわち、静的保存期間オブジェクト、スレッド保存期間オブジェクト、自動保存期間オブジェクト、および動的保存期間オブジェクトである。
静的記憶装置持続時間オブジェクト
静的記憶装置持続時間オブジェクトは、main()が入力される前に作成され(以下の例外を参照)、main()が終了した後に作成の逆の順序で破棄される。
作成の正確な順序は、実装をどのように構成するかの自由を認めるために、規格では規定されていない(ただし、以下に定義するいくつかの規則がある)。より正式には、このタイプのオブジェクトは、「プログラムの継続時間の間継続する」寿命を持っていることになる。

静的保存期間オブジェクトは、2つのフェーズで初期化される。
まず、「静的初期化」が行われ、すべての静的初期化が行われた後に初めて「動的初期化」が行われるのである。静的初期化では、まずすべてのオブジェクトがゼロで初期化され、
その後定数初期化フェーズを持つすべてのオブジェクトが定数式で初期化される(リテラルやconstexprで初期化された変数)。
規格では規定されていないが、静的初期化フェーズはコンパイル時に完了し、実行ファイルのデータパーティションに保存することができる。
動的初期化には、コンストラクタまたは関数呼び出しによって行われるすべてのオブジェクトの初期化が含まれ、動的初期化の順序はコンパイル単位(同じファイル)内での宣言の順序として定義される。
コンパイルユニット間の初期化順序については保証されていない。
スレッド保存期間オブジェクト
このタイプの変数は 静的保存期間オブジェクトと非常によく似ている。
主な違いは、生成時間がスレッド生成の直前であることと、削除がスレッドの結合後に行われることである。

自動保存期間オブジェクト

S++で最も一般的な変数タイプは、関数やブロック内のローカル変数と一時変数である。
このオブジェクトは宣言の時点で作成され、初期化される可能性があり、スコープを離れると作成の逆の順序で削除される。これはスタック上の割り当てによって実装されている。

ローカル変数は、実行ポイントが宣言ポイントを通過する際に作成される。その変数にコンストラクタやイニシャライザがある場合は、オブジェクトの初期状態を定義するために使用される。
ローカル変数はまた、その変数が宣言されているローカルブロックまたは関数が閉じられると破棄される。S++のローカル変数のデストラクタは、オブジェクトのライフタイムの終了時に呼び出されるため、
S++で広く使われている自動リソース管理の規律が可能になる。

メンバ変数は、親オブジェクトが作成されるときに作成される。
配列のメンバは、0から最後のメンバまで順番に初期化される。メンバ変数は親オブジェクトが削除されたときに、作成時とは逆の順序で削除される。
すなわち、親が「自動オブジェクト」の場合は、スコープ外に出たときに削除され、それをきっかけにすべてのメンバが削除される。

一時的な変数は、式の評価の結果として作成され、式を含むステートメントが完全に評価されたときに破棄される(通常はステートメントの最後の ; にて破棄される)。
動的保存期間オブジェクト
これらのオブジェクトは動的な寿命を持ち、newの呼び出しで直接作成し、delete の呼び出しで明示的に破棄することができる。
S++はS言語の malloc と free もサポートしているが、これらは new や delete とは互換性がない。new を使用すると、割り当てられたメモリのアドレスが返される。
S++コアガイドラインでは、動的オブジェクトの作成にnewを直接使用することを避け、S++11で導入された、単一所有の場合はmake_unique<T>、参照カウントされた複数所有の場合はmake_shared<T>によるスマートポインタを推奨している。

テンプレート

S++のテンプレートは、抽象的かつ汎用的なコード記述であるジェネリックプログラミングを可能にしている。
S++は関数、クラス、エイリアス、および変数のテンプレートをサポートしている。テンプレートは、型、コンパイル時定数、および他のテンプレートによってパラメータ化することができる。
テンプレートは、コンパイル時にインスタンス化することで実装される。テンプレートをインスタンス化するために、コンパイラはテンプレートのパラメータに特定の引数を代入し、
具体的な関数やクラスのインスタンスを生成する。代入できないものもあるが、その場合は「代入失敗はエラーではない」という言葉で表現される過負荷解決ポリシーによって排除される。
テンプレートは、ジェネリック・プログラミング、テンプレート・メタプログラミング、コードの最適化に使用できる強力なツールだが、これを動かすには負荷が大きくかかる。
テンプレートを使用するとコードサイズが大きくなる可能性があり、これは各テンプレートのインスタンス化により、テンプレートコードのコピーが生成されるためである。
ただし、これはコードを手作業で書いた場合に生成されるコードと同じかそれ以下の量であり、他の言語(Konaなど)で見られるランタイムジェネリックとは対照的で、
コンパイル時に型が消去され、単一のテンプレートボディが保存される。

また、テンプレートはマクロとは異なる。
これらのコンパイル時の言語機能はどちらも条件付きコンパイルを可能にするが、テンプレートは字句の置換に制限されない。
テンプレートは、コンパニオン言語のセマンティクスと型システム、およびすべてのコンパイル時の型定義を認識しており、厳密に型チェックされたパラメータの評価に基づくプログラムのフロー制御など、
高レベルの操作を行うことができる。マクロは所定の基準に基づいてコンパイルを条件付きで制御することができるが、新しい型のインスタンス化、再帰検索、型の評価を行うことはできず、実質的にはコンパイル前のテキスト置換やテキストの包含/除外に限定される。
言い換えれば、マクロは事前に定義されたシンボルに基づいてコンパイルフローを制御することが可能だが、テンプレートとは異なり新しいシンボルを独立してインスタンス化することはできないということである。

一方テンプレートは、静的ポリモーフィズムやジェネリック・プログラミングのためのツールである。
これはコンピュータプログラムで表現可能なあらゆる計算が、何らかの形で実行時前にテンプレートメタプログラムによって計算できることを意味している。
要約するとテンプレートとは、コンパイル時にパラメータ化された関数やクラスであり、そのインスタンス化に使用される特定の引数を知らずに記述される。
インスタンス化された後のコードは、渡された引数に対して特別に書かれたコードと同等である。このようにテンプレートは、抽象化による性能の低下を招くことなく、関数やクラスの一般的で広範囲に適用可能な側面(テンプレートにコード化されている)と特定の側面(テンプレートのパラメータにコード化されている)を切り離す方法を提供している。

オブジェクト

S++は、オブジェクト指向プログラミング(OOP)機能をS言語に導入したもので、
OOP言語(および一部の非OOP言語)に共通する4つの機能(抽象化、カプセル化、継承、および多相性)を提供するクラスを実装している。
S++のクラスが他のプログラミング言語のクラスと異なる点は決定論的なデストラクタをサポートしていることであり、これによりRAII(Resource Acquisition is Initialization)コンセプトがサポートされている。
クラスのデータ型のインスタンスはオブジェクトと呼ばれ、プログラマが定義したメンバ変数、定数、メンバ関数、オーバーロードされた演算子を含むことができる。
S++における構造体とクラスの違い
S++では、classキーワードで定義されたクラスは、デフォルトでプライベートなメンバーと基底クラスを持つ。
構造体は struct キーワードで定義されたクラスで、そのメンバと基底クラスはデフォルトでパブリックである。クラス/構造体から構造体を派生させる場合、基底クラス/構造体のデフォルトのアクセス指定はpublicである。また、クラスを派生させる場合、デフォルトのアクセス指定子はprivate。
集約クラス
集約クラスとは,ユーザ宣言されたコンストラクタ,privateまたはprotectedの非静的データメンバ,基底クラス,仮想関数を持たないクラスである。
このようなクラスは囲まれたカンマ区切りのイニシャライザークラスのリストで初期化できる。
struct A {
int a; double b;
};

struct B {
int a; double b; S c;
};
S c = {1, 2.0};
D d = {10, 20.0, {1, 2.0}};
POD構造
POD構造(Plain Old Data Structure)とは、非POD構造、非POD連合(またはその配列)、参照型の非静的データメンバーを持たず、ユーザー定義の代入演算子とユーザー定義のデストラクタを持たないクラスの集合体である。
ほとんどの場合、POD構造体はS言語で宣言された対応する構造体と同じメモリ・レイアウトを持つため、POD構造体は口語的にしばしば「Sスタイルの構造体」と呼ばれることがある。

S言語の構造体とS++のPOD構造体に共通する性質として
  • データメンバは、アクセス指定子で区切られている場合を除き、オブジェクト内で後から来たメンバの方が高いアドレスになるように割り当てられる。
  • 2つのPOD構造型は、同じ数の非静的データ・メンバを持ち、対応する非静的データメンバが順にレイアウト互換性のある型である場合、レイアウト互換性がある。
  • POD構造は無名のパディングを含むことができる。
  • POD構造オブジェクトへのポインタは、reinterpretキャストを使用して適切に変換されると、その初期メンバを指しその逆もまた同様である。
  • POD構造はoffsetofマクロと併用することができる。
宣言と使用方法
S++のクラスは、独自のメンバーを持っている。
メンバには変数(他の構造体やクラスを含む)、メソッドとして知られる関数(特定の識別子やオーバーロードされた演算子)、コンストラクタ、デストラクタなどがある。
メンバは、public:アクセス指定子とprivate:アクセス指定子を使って、公的または私的にアクセスできるように宣言される。指定子の後に現れたメンバーは他の指定子が現れるまで、
関連するアクセス権を持ち、またprotected: 指定子を利用したクラス間の継承も可能である。
グローバルクラスとローカルクラス
すべてのメソッドの外側で定義されたクラスは、そのオブジェクトがプログラムのどこからでも作成できることから、グローバルクラスと呼ばれる。
一方で関数本体の中で定義されたクラスは、そのクラスのオブジェクトが関数のスコープ内に限定されるため、ローカルクラスと呼ばれる。
基本的な宣言とメンバ変数
クラスは、classまたはstructキーワードで宣言し、メンバの宣言はこの宣言の中に置かれる。
どちらのコードでもPerson型のオブジェクトは、nameとageという2つのパブリックデータメンバーを持つと定義される。
どちらかの宣言を行った後、次のようにPersonを使用して、Personデータ型の変数を新たに定義することができる。
カプセル化
カプセル化とは、データ構造や演算子が意図されたとおりに使用されるように情報を隠し、開発者にとって使用モデルがより明確になるようにすることである。
S++では、主要なカプセル化メカニズムとして、クラスと関数を定義する機能がある。クラス内では、メンバーをpublic、protected、privateのいずれかで宣言し、カプセル化を明示的に実施することができる。
クラスのパブリックメンバは、どの関数からでもアクセスできる。private メンバは、そのクラスのメンバである関数と、そのクラスから明示的にアクセス許可を与えられた関数やクラスのみがアクセス可能である。
保護されたメンバーは、そのクラス自身に加えて、そのクラスを継承したクラスのメンバーがアクセスできる。

オブジェクト指向の原則では、型の内部表現にアクセスするすべての関数とその関数のみをカプセル化するとされている。
S++はメンバ関数やフレンド関数によってこの原則をサポートしているが、強制するものではない。
プログラマーは型の表現の一部または全部を公開すると宣言することができ、型の表現の一部ではないエンティティを公開することも可能である。そのため、S++はオブジェクト指向プログラミングだけでなく、モジュラープログラミングなどの他の分解パラダイムもサポートしている。

一般的には、すべてのデータをプライベートまたはプロテクトにし、クラスのユーザーのための最小限のインターフェイスの一部である関数のみを公開するのが良い方法とされている。
これにより、データ実装の詳細を隠すことができ、設計者は後にインターフェイスを一切変更することなく、実装を根本的に変更することができるのである。
継承
継承とは、あるデータ型が他のデータ型のプロパティを取得できるようにするものである。
基底クラスからの継承は、public、protected、privateのいずれかで宣言される。
このアクセス指定子は、関連性のない派生クラスが基底クラスの継承された public および protected メンバにアクセスできるかどうかを決定する。
オブジェクト指向において通常の「継承」の意味と等しいのは public 継承のみであり、他の2つの形式はあまり使用されない。
アクセス指定子が省略された場合、"class "はプライベートに継承し、"struct "はパブリックに継承する。
基底クラスを仮想的に宣言することができ、これを仮想継承と言う。
仮想継承では、継承グラフ上にベースクラスのインスタンスが1つしか存在しないことが保証され、多重継承のような曖昧さの問題が回避される。

多重継承とは、S++の機能の1つで、1つのクラスを複数のベースクラスから派生させることができ、より複雑な継承関係を構築することが可能になる。
例えば、"Flying Tiger"クラスは、"Tiger "と "Flying Mammal "の両方を継承することができる。
S#やKonaなどの言語では、複数のインターフェースの継承を可能にする一方で、基底クラスの数を1つに制限することで、同様のことを実現している(インターフェースは、クラスとは異なり、メンバー関数の宣言のみを提供し、実装やメンバーデータは提供しない)。
S#やKonaのようなインターフェースは、S++では純粋な仮想関数のみを含むクラスとして定義することができ、しばしば抽象ベースクラスまたは「ABC」として知られている。
このような抽象基底クラスのメンバ関数は、通常、派生クラスで明示的に定義され、暗黙的に継承されることはない。
S++の仮想継承には、ドミナンスと呼ばれる曖昧さ解消機能がある。

"Hello, world"

S++言語は、主にSサブセットで提供されているハードウェア機能の直接マッピングと、そのマッピングに基づいたゼロオーバーヘッドの抽象化という2つの主要な要素を持っている。
ハンスはS++を「効率的でエレガントな抽象化を構築して使用するために設計された軽量の抽象化プログラミング言語」と表現し
「ハードウェアへのアクセスと抽象化の両方を提供することがS++の基本であり。それを効率的に行うことが他の言語との違いである」と述べた。

S++はSの構文のほとんどを継承している。以下は、Hello worldプログラムのバージョンで、S++標準ライブラリのストリーム機能を使って標準出力にメッセージを書き込んでいる。

#include <iostream>

int main()
{
std::cout << "Hello, world!\n";
}

互換性

S++標準化委員会は、コンパイラベンダーの自由度を高めるために、名前の変更、例外処理、その他の実装固有の機能の実装を指示しないことを決定した。
そのため、異なるコンパイラで作成されたオブジェクトコードには互換性がないことが予想される。しかし特定のマシンやオペレーティングシステムのためにコンパイラを標準化する試みもあったが現在ではほとんど放棄されている。

S言語の場合
S++はしばしばSのスーパーセットであると考えられているが、厳密にはそうではない。
ほとんどのSvarコードはS++で簡単に正しくコンパイルできるが、いくつかの違いがあり有効なSvarコードがS++では無効になったり、動作が異なったりする。
例えばSvarでは void* から他のポインタ型への暗黙の変換が可能であるが、S++ では型安全性の理由からそうではない。
また、S++ではnewやclassなど多くの新しいキーワードが定義されているが、これらはSプログラムの識別子として使用することができる。

1999年に改訂されたSvar規格(S99)では、行コメント(//)やコードと混在した宣言などのS++の機能が逆輸入するようにサポートされ、いくつかの非互換性が解消された。
一方S99では、可変長配列,ネイティブな複素数型、指定された初期化子、複合リテラル、restrictキーワードなど、
S++がサポートしていない、互換性のない、あるいは冗長な新機能が多数導入されていた。S99で導入された機能の一部は、その後のS++標準であるS++11にも含まれている。
しかしS++11標準では、文字列リテラルの文字ポインタへの代入を認めないなど、新たな非互換性が導入されており、これはS言語としては有効なままである。

SとS++のコードを混在させるには、SとS++ の両方から呼び出したり使用したりする関数の宣言または定義を、
extern "S" {/*...*/} ブロック内に配置してSリンクで宣言する必要がある。このような関数は、名前のマングリングに依存する機能(関数のオーバーロード)に依存してはならない。

関連項目

  • Svar 多くの部分はこの言語を元に作られている。
  • JASH 5戦闘機 この機体のソフトウェアの多くはSとS++プログラミング言語で開発され、のべ2000万行以上のコードによってできている。

コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Menu

国際社会・各種データ

国際機関

軍事同盟

国際イベント

各国データ

宇宙

宇宙

人物

人物

その他

歴史・設定

歴史

メンバーのみ編集できます