【C++】C++の型変換
記事ディレクトリ
1. C言語での型変換
C 言語では、型変換は、式または変数の値をあるデータ型から別のデータ型に変換するプロセスです。C 言語には、型変換を実行するためのいくつかの型変換演算子と関数が用意されています。
一般的な型変換メソッドをいくつか示します。
- 型キャスト: キャスト演算子を使用して、
(type)
式または変数を指定されたデータ型にキャストします。たとえば、(int)3.14
浮動小数点数 3.14 を整数に変換します。
double pi = 3.14;
int approxPi = (int)pi;
- 自動型変換 (暗黙的変換): C 言語の一部のデータ型間には、暗黙的な型変換規則があります。たとえば、整数を浮動小数点変数に代入する場合、C 言語は自動的に整数を浮動小数点数に変換します。
int num = 10;
float floatNum = num; // 自动将整数转换为浮点数
- 数値型間の変換規則: 数値型間の変換では、C 言語は特定の変換規則に従います。たとえば、浮動小数点数と整数の演算を実行する場合、C 言語は自動的に整数を浮動小数点数に変換してから演算を実行します。
int num = 10;
float result = 3.14 + num; // 整数转换为浮点数,然后相加
atoi()
型変換関数を使用する: C 言語には、文字列と数値型の間で変換するための、 、atof()
、などのいくつかの型変換関数が用意されていますitoa()
。
char str[] = "123";
int num = atoi(str); // 字符串转换为整数
次の点に注意してください。
- 型変換により、データの損失または切り捨てが発生する可能性があります。たとえば、浮動小数点数を整数に変換する場合、小数部分は切り捨てられます。
- 互換性のない型変換を実行する場合は、データ型の範囲と精度に注意する必要があります。オーバーフローや精度の低下が発生する可能性があります。
- C言語には型変換の機能がありますが、過度な型変換はコードの可読性や保守性を低下させる可能性があるため、使用には注意が必要です。
これらは、C 言語での一般的な型変換方法と考慮事項です。特定のアプリケーション シナリオと要件に応じて、データ型間の変換を処理する適切な型変換方法を選択できます。
2. C++の型変換
2.1 4種類の変換
C スタイルの変換形式は非常にシンプルですが、多くの欠点があります。
- 暗黙的な型変換は、データ精度の損失など、場合によっては問題を引き起こす可能性があります。
- 明示的な型変換ではすべてのケースが混在し、コードが十分に明確ではないため、C++ は独自の型変換スタイルを提案しています。C++ は C 言語と互換性があるため、C 言語の変換スタイルは C++ でも使用できることに注意してください。
C++ では、さまざまなプログラミング ニーズやセマンティック要件を満たす、より柔軟で正確な型変換メカニズムを提供するために 4 種類の変換が導入されています。変換には次の 4 種類があります。
-
静的キャスト: 静的キャストは最も一般的な型変換であり、コンパイル時に実行され、あるデータ型を別のデータ型に変換できます。これは、暗黙的な変換 (整数から浮動小数点数への変換など) または明示的な変換 (基本クラス ポインターから派生クラス ポインターへの変換など) に使用できます。静的変換には実行時の型チェックがないため、変換が安全であることを確認するのは開発者の責任です。
-
動的キャスト (Dynamic Cast): 動的キャストは主に、継承関係におけるポインターまたは参照を処理するために使用されます。実行時にポインターまたは参照の実際の型をチェックし、それに応じて変換できます。変換が安全でない場合、つまりソース ポインターまたは参照がターゲット型の有効なオブジェクトではない場合、動的変換は null ポインター (ポインターの場合) を返すか、例外 (参照の場合) をスローします
std::bad_cast
。 -
定数変換 (Const Cast): 定数変換は、式の定数性 (const) を削除したり、定数性を追加したりするために使用されます。これは主に、特定の状況で定数オブジェクトの値を変更するために使用されますが、使用には注意が必要です。定数変換では式の定数を変更できますが、実際のオブジェクトを変更することはできません。
-
再解釈キャスト: 再解釈キャストは、ポインターまたは参照をまったく無関係な型に変換する下位レベルのキャストです。この変換の結果は、元のビット パターンの再解釈であり、整数からポインターへの変換やポインターから整数への変換など、基礎となる型変換を処理するためによく使用されます。
これら 4 種類の変換は異なるセマンティクスと動作を提供するため、プログラマは型変換のプロセスをより細かく制御できます。しかし同時に、開発者は、潜在的な実行時エラーや未定義の動作を回避するために、型変換の安全性と正確性を確保するために、それらを使用する際には注意する必要もあります。
2.2 必須の型変換
2.2.1 静的キャスト
static_cast
C++ の型変換演算子であり、コンパイル時の静的型変換を実行するために使用されます。暗黙的な変換と明示的な変換を含めて、あるデータ型を別のデータ型に変換できます。
を使用するとstatic_cast
、コンパイラはコンパイル時に型変換の正当性をチェックしますが、実行時の型チェックは行いません。したがって、開発者は、潜在的な型エラーを回避するために、変換が安全であることを確認する必要があります。
以下にstatic_cast
いくつかの使用法を示します。
- 暗黙的な変換:
static_cast
暗黙的な型変換を実行するために使用できます。たとえば、整数型を浮動小数点型に変換します。
int num = 10;
double result = static_cast<double>(num); // 隐式将整数转换为浮点数
- 明示的な変換:
static_cast
ポインターまたは参照をある型から別の型に変換するなど、明示的な型変換を実行することもできます。
Base* basePtr = new Derived(); // Derived 是 Base 的派生类
Derived* derivedPtr = static_cast<Derived*>(basePtr); // 将基类指针转换为派生类指针
- 数値型の変換:
static_cast
数値型の拡張および縮小変換を含む、数値型間の変換を実行できます。
int num = 10;
char charValue = static_cast<char>(num); // 将整数转换为字符类型(可能会发生截断)
次の点に注意してください。
static_cast
プリミティブ データ型間の変換や、継承関係のあるポインターまたは参照間の変換など、明確に定義された型変換でのみ使用できます。static_cast
const
、volatile
または修飾子の削除には使用できません__unaligned
。このような場合には、const_cast
または他の適切な型変換演算子を使用してください。static_cast
関連性のない型間の変換の実行や、低レベルの再解釈変換の実行には使用できません。このような場合、reinterpret_cast
を使用して変換を実行できます。
全体として、static_cast
一般的な型変換要件を処理できる、コンパイル時の型変換のメカニズムを提供します。ただし、型変換が安全かつセマンティックであることを保証するために、これを使用する場合は注意が必要です。
2.2.2 再解釈キャスト
reinterpret_cast
は、低レベルの再解釈変換を実行する C++ の型変換演算子です。ポインタまたは参照をまったく無関係な型に変換できます。つまり、あるオブジェクトのビット パターンを別の型のビット パターンとして再解釈します。
これを使用するreinterpret_cast
と、コンパイラは、型チェックや変換操作を行わずに、指定された型のビット パターンをターゲット型のビット パターンとして再解釈しようとします。これによりreinterpret_cast
、非常に低レベルの変換が行われ、通常は型に依存する低レベルの表現や、特定のハードウェア要件に合わせた型変換を処理するために使用されます。
以下にreinterpret_cast
いくつかの使用法を示します。
- ポインター間の変換:
reinterpret_cast
2 つの型の間に継承関係がない場合でも、ポインターを別の型のポインターに変換できます。
int* intPtr = new int(10);
char* charPtr = reinterpret_cast<char*>(intPtr); // 将 int 指针转换为 char 指针
- 参照間の変換:
reinterpret_cast
参照を別のタイプの参照に変換することもできます。
int num = 10;
char& charRef = reinterpret_cast<char&>(num); // 将 int 引用转换为 char 引用
- 整数からポインターへの変換、またはポインターから整数への変換:
reinterpret_cast
整数値をポインターに、またはポインターを整数値に変換するために使用できます。これは通常、特定のハードウェアに関連する低レベルのポインター操作またはビット パターンを処理するために使用されます。
uintptr_t intValue = reinterpret_cast<uintptr_t>(ptr); // 将指针转换为整数
void* ptr = reinterpret_cast<void*>(intValue); // 将整数转换为指针
次の点に注意してください。
reinterpret_cast
は、型の安全性とセマンティクスに関するコンパイラのチェックをバイパスするため、非常に危険なキャストです。誤って使用すると、未定義の動作やシステムクラッシュが発生する可能性があります。reinterpret_cast
実行される変換はプラットフォームとコンパイラに固有であり、異なるプラットフォームでは異なる結果が生成される場合があります。- 互換性のない型間の変換は避けるべきです
reinterpret_cast
。そのような変換は型システムを破壊し、予測できない動作を引き起こすことがよくあります。
reinterpret_cast
これは非常に低レベルで危険な型変換であるため、慎重に使用し、変換がセマンティクスおよびプラットフォーム要件と一致していることを確認する必要があります。ほとんどの場合、 や など、より安全で意味的に明示的な型変換演算子を優先する必要がありstatic_cast
ますdynamic_cast
。
2.2.3 const_cast
const_cast
これは C++ の型変換演算子で、式の定数性 (const) を削除したり、定数性を追加したりするために使用されます。これは主に、特定の場合に定数オブジェクトの値を変更するため、または非 const オブジェクトを予期する関数に定数オブジェクトを渡すために使用されます。
使用するとconst_cast
、式の定数を変換して変換されたオブジェクトを変更できるようになります。このような変換は場合によっては便利ですが、型の固有の定数に違反しないように細心の注意を払う必要があります。
以下にconst_cast
いくつかの使用法を示します。
- Deconstancy:
const_cast
定数オブジェクトを非定常化し、変更できるようにするために使用できます。
const int num = 10;
int* mutablePtr = const_cast<int*>(&num); // 去除 num 的常量性
*mutablePtr = 20; // 修改 num 的值
- const の追加:
const_cast
非 const オブジェクトを const オブジェクトに変換するためにも使用できます。
int num = 10;
const int& constRef = const_cast<const int&>(num); // 添加 num 的常量性
次の点に注意してください。
const_cast
式の型を変換するのではなく、式の定数を削除または追加するためにのみ使用できます。- 本質的に定数であるオブジェクトを変更することは未定義の動作であり、それを使用して
const_cast
定数オブジェクトを変更すると、予期しない結果やエラーが発生する可能性があります。 const_cast
取得したポインタまたは参照が指す定数オブジェクトを変更することは潜在的に危険な操作であり、変更操作が安全かつ合理的であることを保証する必要があります。
const_cast
定数オブジェクトを変更するメソッドが提供されていますが、使用には注意が必要です。const オブジェクトを変更すると、型の固有の定数に違反し、潜在的なエラーや不確実性が生じる可能性があります。ほとんどの場合、定数の規則に従い、非定数オブジェクトを操作することをお勧めします。
2.2.4 ダイナミックキャスト
dynamic_cast
C++ の型変換演算子であり、実行時の動的な型変換に使用されます。これは主に継承関係におけるポインタまたは参照を処理するために使用され、安全な条件下で基底クラスのポインタまたは参照を派生クラスのポインタまたは参照に変換できるようにします。
使用するとdynamic_cast
、ポインターまたは参照の実際の型が変換のターゲット型と互換性があるかどうかがチェックされます。互換性がある場合、変換は成功し、ターゲット型へのポインタまたは参照を返します。互換性がない場合、変換は失敗し、(ポインタの場合) null ポインタを返すか、(参照の場合) 例外をスローしますstd::bad_cast
。
以下にdynamic_cast
いくつかの使用法を示します。
- ポインター間の変換:
dynamic_cast
基本クラス ポインターを派生クラス ポインターに変換できますが、基本クラス ポインターが指すオブジェクトがターゲットの派生クラスのオブジェクトであることを確認する必要があります。
class Base {
virtual void print() {
}
};
class Derived : public Base {
};
Base* basePtr = new Derived(); // Derived 是 Base 的派生类
Derived* derivedPtr = dynamic_cast<Derived*>(basePtr); // 将基类指针转换为派生类指针
- 参照間の変換:
dynamic_cast
基本クラス参照を派生クラス参照に変換することもできます。基本クラス参照によって参照されるオブジェクトがターゲットの派生クラスのオブジェクトであることを確認する必要があります。
Base& baseRef = derivedObj; // derivedObj 是 Derived 类型的对象
Derived& derivedRef = dynamic_cast<Derived&>(baseRef); // 将基类引用转换为派生类引用
- ポリモーフィックな型変換:
dynamic_cast
ポリモーフィックな状況で非常に便利です。基本クラスのポインターまたは参照を特定の派生クラスへのポインターまたは参照に変換し、派生クラスのメンバー関数を安全に呼び出すことができます。
class Base {
public:
virtual void print() {
}
};
class Derived : public Base {
public:
void print() override {
cout << "Derived" << endl; }
};
Base* basePtr = new Derived(); // Derived 是 Base 的派生类
Derived* derivedPtr = dynamic_cast<Derived*>(basePtr); // 将基类指针转换为派生类指针
derivedPtr->print(); // 调用派生类的成员函数
次の点に注意してください。
dynamic_cast
基本クラスに少なくとも 1 つの仮想関数が含まれる多態性クラス階層でのみ使用できます。dynamic_cast
変換対象の型は継承関係のあるクラス型である必要があります。そうでない場合、変換は失敗します。- 変換が失敗すると、
dynamic_cast
ポインター型の場合は null ポインターが返され、std::bad_cast
参照型の場合は例外がスローされます。ポインターを使用する場合は Null ポインター チェックを実行する必要があり、参照を使用する場合は例外処理メカニズムを使用する必要があります。
全体として、dynamic_cast
継承関係におけるポインターまたは参照を処理するために実行時に型変換するメカニズムを提供します。安全な条件下で、基本クラスのポインターまたは参照を派生クラスのポインターまたは参照に変換でき、派生クラス固有のメンバー関数を呼び出すことができます。
3、RTTI
RTTI (実行時型情報) は、実行時にオブジェクトの型情報を取得するために使用される C++ の機能です。これは、プログラムが実行時にオブジェクトの実際の型を動的に判断し、対応する型チェックと型変換を実行できるメカニズムを提供します。
C++ の RTTI は主に 2 つの主要なコンポーネントで構成されています。
typeid
演算子:typeid
演算子は、オブジェクトの型情報を取得するために使用されます。std::type_info
型の名前など、実際の型に関する情報を含むオブジェクトを返します。
#include <typeinfo>
Base* basePtr = new Derived(); // Derived 是 Base 的派生类
const std::type_info& typeInfo = typeid(*basePtr); // 获取对象的类型信息
dynamic_cast
演算子:dynamic_cast
演算子は、実行時に動的型変換を実行し、変換が安全かどうかを確認するために使用されます。RTTI 情報を使用してオブジェクトの実際の型を判断し、適切な型変換を実行します。
Base* basePtr = new Derived(); // Derived 是 Base 的派生类
Derived* derivedPtr = dynamic_cast<Derived*>(basePtr); // 将基类指针转换为派生类指针
次の点に注意してください。
typeid
演算子 とdynamic_cast
演算子 は、基本クラスに少なくとも 1 つの仮想関数が含まれる多態性クラス階層にのみ適用されます。- RTTI を使用するには、ヘッダー ファイルをインクルードする必要があります
<typeinfo>
。 - RTTI 情報の利用可能性は、コンパイラおよびコンパイル オプションによって影響を受ける可能性があります。場合によっては、RTTI を使用するために特定のコンパイル オプションを有効にする必要がある場合があります。
- RTTI を使用するには、特に頻繁に呼び出されるシナリオでは、実行時のオーバーヘッドに注意する必要があります。
要約すると、RTTI は、実行時にオブジェクト型情報を取得するために C++ によって提供されるメカニズムです。typeid
演算子を通じて型情報を取得し、演算子dynamic_cast
を通じて動的な型変換と型チェックを実行します。RTTI を使用すると、より柔軟なオブジェクト操作を実現できますが、実行時のオーバーヘッドと適用性の制限に注意する必要があります。
コンパイラおよびコンパイル オプションの影響を受ける可能性があります。場合によっては、RTTI を使用するために特定のコンパイル オプションを有効にする必要がある場合があります。