「型変換」の版間の差分

削除された内容 追加された内容
編集の要約なし
編集の要約なし
20行目:
この[[C言語]]のコードでは、<code>d</code>と<code>l</code>と<code>i</code>は異なったデータ型をもっているので、すべての演算は自動的に同じ型に変換された後に行われる。より大きなサイズの型に変換されることを拡大変換 (widening conversion) と呼び、より小さなサイズの型に変換されることを縮小変換 (narrowing conversion) と呼ぶ。
 
暗黙の型変換には注意しなければならないこともある。たとえば<code>double</code>型([[浮動小数点数]])の値を<code>int</code>型([[整数型]])の変数に代入する場合、小数点以下の端数があったり、元の値が<code>int</code>型で表現できる範囲を超えていたりすると、縮小変換により情報の一部が失われてしまう。浮動小数点数特有の誤差により、意図せず切り捨てられてしまうこともありうる。また、符号付き整数と符号無し整数との間の暗黙変換に関しても、同様に情報が失われたり、整数オーバーフローにより意図しない値になってしまったりする可能性がある。C言語および[[C++]]では暗黙の縮小変換を許しているが、情報が失われる可能性のある変換に対して、通例[[コンパイラ]]が警告を出す。[[Java]]や[[C Sharp|C#]]などの後発言語では、暗黙の縮小変換を許可せず、後述するキャスト (cast) 構文による明示的な変換が必要となる。さらに型の扱いが厳密な[[F Sharp|F#]]などの関数型言語では、暗黙の拡大変換も許可せず、キャスト構文による明示的な型変換が必要となる。
 
===組み込みの型変換とユーザー定義の型変換===
59行目:
 
==== アップキャスト ====
あるクラス<tt>Base</tt>と、<tt>Base</tt>から派生したクラス<tt>Derived</tt>があるとする。アップキャストとは、派生クラスから基底クラスへの型変換、すなわち<tt>Derived</tt>のインスタンスを<tt>Base</tt>に変換する操作である。「<tt>Derived</tt>のインスタンスは<tt>Base</tt>のインスタンスである」ことは保証されているので、一般的には{{要説明|date=2019-12}}この変換は安全である。そのため、多くの言語において、これは暗黙に行うことができる([[リスコフの置換原則]])
 
ただし、[[C++]]において多重継承のクラスのアップキャストが安全でないとされる環境{{要出典|date=2014年11月}}{{要説明|date=2019-12}}では、<tt>dynamic_cast</tt>を使うことが推奨される{{要出典|date=2014年11月}}{{要説明|date=2019-12}}。
 
==== ダウンキャスト ====
ダウンキャストはアップキャストの逆で、基底クラスから派生クラスへの型変換、すなわち<tt>Base</tt>のインスタンスを<tt>Derived</tt>に変換する操作である。<tt>Base</tt>のインスタンスは必ずしも<tt>Derived</tt>のインスタンスとは限らないので、この変換は一般に安全ではなく、エラーが発生する可能性がある。そのため、多くの言語ではキャスト構文による明示的な変換の記述が必要である。通例、[[オブジェクト指向プログラミング]]では[[ポリモーフィズム]]を使うべきであり、ダウンキャストおよびクロスキャストが必要になるということはプログラムの設計に問題があることを示唆している。
 
[[C++]]では、安全なダウンキャストのために<code>dynamic_cast</code>という特別な構文が用意されている。この構文では、[[実行時型情報]]を参照し、ポインタ間の変換が失敗すると結果として<tt>[[ヌルポインタ#C++|NULL]]</tt>が返る。参照間の変換が失敗すると<code>std::bad_cast</code>例外がスローされる。<code>dynamic_cast</code>を使用するためには、型に[[仮想関数テーブル]]が必要となる。つまり、基底クラスに少なくとも1つの仮想関数を持つ必要がある。確実に成功することが分かっているダウンキャストの場合は<code>static_cast</code>で代用でき、これは<code>dynamic_cast</code>よりも実行時コストが小さくなるが、失敗する可能性のある場合には使えない。単一継承の場合はダウンキャストにC言語形式のキャスト構文を使うこともできるが、多重継承の場合はダウンキャストに<code>dynamic_cast</code>または<code>static_cast</code>を使う必要があり、またどの基底クラスへのポインタにキャストするかによって結果アドレスが変化しうる。
 
[[Java]]では、ダウンキャストに失敗すると{{Javadoc:SE|name=java.lang.ClassCastException|java/lang|ClassCastException}}例外がスローされる。C++の<code>dynamic_cast</code>に相当する機能は存在しないが、<code>instanceof</code>演算子で型情報を問い合わせることはできる。
80行目:
 
C++では、ダウンキャストと同じ構文<code>dynamic_cast</code>で安全なクロスキャストが行える。
 
[[C++/CLI]]および{{仮リンク|C++/CX|en|C++/CX}}ではそれぞれ、<code>safe_cast</code>構文による[[マネージコード|マネージ]]型間あるいは[[Windowsランタイム]]型間のダウンキャストおよびクロスキャストをサポートし、失敗すると<code>System.InvalidCastException</code>例外がスローされる<ref>[https://docs.microsoft.com/en-us/cpp/cpp/casting-operators Casting Operators | Microsoft Docs]</ref><ref>[https://docs.microsoft.com/en-us/cpp/extensions/safe-cast-cpp-component-extensions safe_cast (C++/CLI and C++/CX) | Microsoft Docs]</ref>。
 
==== 静的キャスト ====
89 ⟶ 91行目:
== 関連項目 ==
* [[型システム]]
* [[汎整数拡張]]
 
{{DEFAULTSORT:かたへんかん}}