static_cast 変換
提供: cppreference.com
暗黙の変換とユーザ定義変換の組み合わせを用いて型の間で変換します。
目次 |
[編集] 構文
static_cast < new_type > ( expression )
|
|||||||||
new_type
型の値を返します。
[編集] 説明
以下の変換のみが static_cast を用いて行うことができます。 ただし cv 修飾を除去することはできません。
1) expression から new_type への暗黙の変換シーケンスが存在する場合、または expression から new_type 型のオブジェクトまたは参照の直接初期化に対するオーバーロード解決が少なくとも1個の適用可能な関数が見付かる場合、 static_cast<new_type>(expression) は new_type Temp(expression); によって行われたかのように初期化された架空の変数
Temp
を返します。 これは暗黙の変換、 new_type のコンストラクタの呼び出し、またはユーザ定義変換演算子の呼び出しを発生させることがあります。 非参照の new_type の場合、 static_cast prvalue 式の結果のオブジェクトは直接初期化されたオブジェクトです。 (C++17以上)2) new_type が何らかのクラス
D
へのポインタまたは参照であり、 expression の型がその非仮想基底 B
へのポインタまたは参照である場合、 static_cast
はダウンキャストを行います。 B
が曖昧であるか、アクセスできないか、 D
の仮想基底 (または仮想基底の基底) の場合、このダウンキャストは ill-formed です。 このような static_cast
は、そのオブジェクトの実行時の型が実際に D
であることを保証するための実行時チェックを行わず、この事前条件が他の方法で保証できる場合 (静的ポリモーフィズムを実装するときなど) にのみ安全に使用できます。 安全なダウンキャストは dynamic_cast で行うことができます。
3) new_type が右辺値参照型の場合、 static_cast は glvalue、クラスの prvalue、または配列の prvalue (C++17未満)任意の lvalue (C++17以上) expression の値を、その式と同じオブジェクトを参照する xvalue またはその基底部分オブジェクト (new_type に依存します) に変換します。 ターゲット型がアクセスできないまたは式の型の曖昧な基底の場合、プログラムは ill-formed です。 式がビットフィールド lvalue の場合、それはまずそのベースとなる型の prvalue に変換されます。 この種の static_cast はムーブセマンティクスを実装するために std::move 内で使用されます。
|
(C++11以上) |
4) new_type が void 型 (cv 修飾されていても構いません) の場合、
static_cast
は expression を評価した後、その値を破棄します。5) new_type から expression の型への標準変換が存在し、それが左辺値から右辺値、配列からポインタ、関数からポインタ、ヌルポインタ、ヌルメンバポインタ、関数ポインタ、 (C++17以上)またはブーリアン変換を含まない場合、
static_cast
はその暗黙の変換の逆変換を行います。6) expression の new_type への変換が左辺値から右辺値、配列からポインタ、または関数からポインタへの変換を発生させる場合、それは
static_cast
によって明示的に行うことができます。7) スコープ付き列挙(C++11)型は整数または浮動小数点型に変換できます。
ターゲット型が cv bool のとき、元の値がゼロの場合は結果は false、それ以外のすべての値に対しては true です。 それ以外の整数型に対しては、結果はその列挙の値がターゲット型で表現可能であればその値、そうでなければ未規定です。 |
(C++20未満) |
結果は列挙のベースとなる型から結果の型への暗黙の変換と同じです。 |
(C++20以上) |
8) 整数または列挙型の値は任意の完全な列挙型に変換できます。
- ベースとなる型が固定でない場合、 expression の値が範囲外であれば (範囲はターゲット列挙型のすべての列挙子を保持するために十分大きな最小のビットフィールドに対するすべての有り得る値です)、結果は未規定 (C++17未満)未定義動作 (C++17以上)です。
- ベースとなる型が固定の場合、結果は、元の値をまずその列挙のベースとなる型に変換し、その後その列挙型に変換したのと同じです。
浮動小数点型の値も任意の完全な列挙型に変換できます。
- 結果は、元の値をまずその列挙のベースとなる型に変換し、その後その列挙型に変換したのと同じです。
9) 何らかのクラス
D
のメンバへのポインタは、その曖昧でないアクセス可能な基底クラス B
のメンバへのポインタにアップキャストできます。 この static_cast
は、指す先のオブジェクトの実行時の型にそのメンバが実際に存在することを保証するためのチェックを行いません。10) void (cv 修飾されていても構いません) へのポインタ型の prvalue は、任意のオブジェクト型へのポインタに変換できます。 元のポインタ値がターゲット型のアライメント要件を満たさないバイトのアドレスを表す場合、結果のポインタ値は未規定です。 そうでなく、元のポインタ値がオブジェクト a を指し、 a とポインタ相互変換可能 (後述) なターゲット型 (cv 修飾は無視します) のオブジェクト b が存在する場合、結果は b へのポインタです。 そうでなければ、ポインタ値は変更されません。 任意のポインタの void へのポインタへの変換およびその元の型 (またはより多くcv 修飾されたその型) へのポインタへの逆変換は、その元の値を維持します。
すべてのキャスト式と同様に、
- new_type が左辺値参照型または関数への右辺値参照型の場合、結果は lvalue です。
- new_type がオブジェクト型への右辺値参照型の場合、結果は xvalue です。
- そうでなければ、結果は prvalue です。
以下の場合、2つのオブジェクト a と b はポインタ相互変換可能です。
- それらが同じオブジェクトである。 または、
- 一方が共用体オブジェクトであり、他方がそのオブジェクトの非静的データメンバである。 または、
- 一方が標準レイアウトクラスのオブジェクトであり、他方がそのオブジェクトの最初の非静的データメンバであるか、そのオブジェクトが非静的データメンバを持たない場合は、そのオブジェクトの任意の基底クラスの部分オブジェクトである。 または、
- a と c がポインタ相互変換可能かつ c と b がポインタ相互変換可能であるようなオブジェクト c が存在する。
union U { int a; double b; } u; void* x = &u; // x の値は「u へのポインタ」です。 double* y = static_cast<double*>(x); // y の値は「u.b へのポインタ」です。 char* z = static_cast<char*>(x); // z の値は「u へのポインタ」です。
[編集] ノート
static_cast は、以下のように、関数ポインタを特定の型に変換することによって、関数オーバーロードの曖昧性を解消するために使用することもできます。
std::for_each(files.begin(), files.end(), static_cast<std::ostream&(*)(std::ostream&)>(std::flush));
[編集] キーワード
[編集] 例
Run this code
#include <vector> #include <iostream> struct B { int m = 0; void hello() const { std::cout << "Hello world, this is B!\n"; } }; struct D : B { void hello() const { std::cout << "Hello world, this is D!\n"; } }; enum class E { ONE = 1, TWO, THREE }; enum EU { ONE = 1, TWO, THREE }; int main() { // 1: 初期化変換。 int n = static_cast<int>(3.14); std::cout << "n = " << n << '\n'; std::vector<int> v = static_cast<std::vector<int>>(10); std::cout << "v.size() = " << v.size() << '\n'; // 2: 静的ダウンキャスト。 D d; B& br = d; // 暗黙の変換によるアップキャスト。 br.hello(); D& another_d = static_cast<D&>(br); // ダウンキャスト。 another_d.hello(); // 3: lvalue から xvalue への変換。 std::vector<int> v2 = static_cast<std::vector<int>&&>(v); std::cout << "after move, v.size() = " << v.size() << '\n'; // 4: 値を破棄する式。 static_cast<void>(v2.size()); // 5. 暗黙の変換の逆変換。 void* nv = &n; int* ni = static_cast<int*>(nv); std::cout << "*ni = " << *ni << '\n'; // 6. 配列からポインタへの変換に続くアップキャスト。 D a[10]; B* dp = static_cast<B*>(a); // 7. スコープ付き列挙から整数または浮動小数点への変換。 E e = E::ONE; int one = static_cast<int>(e); std::cout << one << '\n'; // 8. 整数から列挙、列挙から別の列挙への変換。 E e2 = static_cast<E>(one); EU eu = static_cast<EU>(e2); // 9. メンバへのポインタのアップキャスト。 int D::*pm = &D::m; std::cout << br.*static_cast<int B::*>(pm) << '\n'; // 10. void* から任意の型への変換。 void* voidp = &e; std::vector<int>* p = static_cast<std::vector<int>*>(voidp); }
出力:
n = 3 v.size() = 10 Hello world, this is B! Hello world, this is D! after move, v.size() = 0 *ni = 3 1 0
[編集] 欠陥報告
以下の動作変更欠陥報告は以前に発行された C++ 標準に遡って適用されました。
DR | 適用先 | 発行時の動作 | 正しい動作 |
---|---|---|---|
CWG 2254 | C++17 | standard-layout class object with no data members is pointer-interconvertible to its first base class | is pointer-interconvertible to any of its base classes |