c++の4種類の強制タイプ変換

7028 ワード

C++タイプ変換(Cスタイルの強制変換):
C++の基本的なデータ型では,整数型,浮動小数点型,文字型,ブール型の4種類に分類できる.数値型は整数型と浮動小数点型を含む.文字型はcharです.
(1)浮動小数点データを整数変数に付与する場合は、その小数点を捨てる.
(2)整数データを浮動小数点型変数に付与した場合,数値は変わらないが指数形式で格納する.
(3)double型データをfloat型変数に付与する場合,数値範囲オーバーフローに注意する.
(4)文字型データは整数型変数に割り当てることができ,このときは文字のASCIIコードが格納される.
(5)int,shortまたはlong型のデータを1つのchar型変数に付与し,下位8ビットをそのままchar型変数に送る.(6)同じ長さの符号なし型変数に符号型データを付与し,元の符号ビットとともに転送する.
C++強制型変換:
C++言語に4つのキーワードstatic_が追加されましたcast、const_cast、reinterpret_castとdynamic_cast.この4つのキーワードは、タイプ変換を強制するために使用されます.
新しいタイプの強制変換は、さまざまな種類の強制変換を制御できるように、強制変換プロセスをよりよく制御することができます.
C++中スタイルはstatic_cast(content).C++スタイルの強制変換の他の利点は、何をするのかをより明確に示すことです.プログラマーはこのようなコードを一目見れば、強制変換の目的をすぐに知ることができます.
1) static_cast
C++言語でstatic_castは、データ型の強制変換に使用され、あるデータ型を別のデータ型に強制変換します.たとえば、整数データを浮動小数点データに変換します.[例1]C言語で用いられるタイプ変換方式:
int a = 10; int b = 3; double result = (double)a/(double)b;
例1では,整数変数aとbを二重精度浮動小数点型に変換し,除去した.C++言語ではstatic_を使用できますcastキーワードは、以下に示すように強制タイプ変換を行います.[例2]static_castキーワードの使用:
int a = 10; int b = 3; double result = static_cast(a)/static_cast(b);
本例では同様に、整数変数aを二重精度浮動小数点型に変換する.static_を採用castが強制的にデータ型変換を行う場合、変換したいデータ型をカッコに入れ、変換する変数または式をカッコに入れます.フォーマットは次のように要約できます.
使用法:static_cast(変数または式)
これは主に以下のいくつかの用法がある:(1)クラス階層におけるベースクラスと派生クラス間のポインタまたは参照の変換に用いられる上り変換(派生クラスのポインタまたは参照をベースクラス表現に変換する)は安全に下り変換(ベースクラスのポインタまたは参照を派生クラス表現に変換する)を行い、動的タイプチェックがないため安全ではない(2)intをcharに変換するなどの基本データ型間の変換に使用される.この変換の安全も開発者に保証される(3)空ポインタをターゲット型に変換する空ポインタ(4)任意のタイプの式をvoid型に変換する注意:static_castはexpressionのconst、volitaleまたは__unaligned属性を変換できない.
static_cast:C++に組み込まれた基本データ型間の相互変換を実現できます.
クラスに触れるとstatic_castは相互に関連するタイプでのみ相互変換でき,必ずしも虚関数を含まない.
2) const_cast
C言語では、const限定子は通常、変数を限定するために使用され、その変数の値が変更できないことを示すために使用される.
そしてconst_castは,このような修正できない定数特性を強制的に除去するために用いられるが,const_には特に注意が必要である.castは変数を除去するための定数ではなく、定数オブジェクトを指すポインタまたは参照の定数を除去し、定数を除去するオブジェクトはポインタまたは参照でなければならない.
使用法:const_cast(expression)この演算子は、タイプのconstまたはvolatileプロパティを変更するために使用されます.constまたはvolatile修飾に加えてtype_idとexpressionのタイプは同じです.定数ポインタは非常量ポインタに変換され、元のオブジェクトを指します.定数参照は非常量参照に変換され、元のオブジェクトを指します.定数オブジェクトが非常量オブジェクトに変換されます.
[例3]エラーの例:
const int a = 10; const int * p = &a; *p = 20;//compile error int b = const_cast(a);//compile error
この例では2つのコンパイルエラーが発生し、最初のコンパイルエラーは*pであり、定数性があるため、その値は修正できない.もう1つのエラーはconst_ですcast強制変換オブジェクトはポインタまたは参照でなければなりませんが、例3では変数であり、これは許可されません.
[例4]const_castキーワードの使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
include
using namespace std;
int main()
{
const int a = 10;

const int * p = &a;

int *q;

q = const_cast(p);

*q = 20;    //fine

cout <

}
この例では、変数aを定数変数として宣言し、constポインタが変数を指すことを宣言します(この場合、通常ポインタが定数変数を指すと宣言した場合は許可されません.Visual Studio 2010コンパイラはエラーを報告します).
その後、一般的なポインタ*qを定義しました.pポインタをconst_を通過castはその定数性を取り除き,qポインタに付与する.その後、qポインタが指すアドレスの値を変更すると、問題はありません.
最後に結果を印刷し、実行結果は以下の通りである:10 20 002 CFA 4 002 CFA 4 002 CFA 4
実行結果を確認すると、問題が発生し、ポインタpとポインタqはいずれもa変数を指し、アドレスを指している.また、デバッグにより002 CFA 4アドレス内の値が確かに10から20に変更されたことが分かった.これはどういうことなのか.なぜaの値が印刷されるのか、それとも10なのか.
実はこれは良いことで、私たちはa変数の最終的な値が20になっていないことを喜んでいます!変数aは最初から定数変数として宣言され、後のプログラムがどのように処理されても定数であり、変化しません.もしこの変数aが最終的に20になったらどうなるか考えてみましょう.これらの短いプログラムにとって、最後にaが20になったら、qポインタが修正されたことが一目でわかりますが、プロジェクトプロジェクトが非常に膨大になると、プログラムのどこかでqというポインタが現れ、定数aを修正することができます.これは恐ろしいことです.プログラムの抜け穴と言えます.結局変数aを定数と宣言するのは修正したくないので、後で修正できれば怖いです.
例4では「*q=20」文を未定義の行為文と呼び,未定義の行為とは標準的なC++仕様ではこのような文の具体的な行為が明確に規定されていないことを意味し,その具体的な行為はコンパイラによってどのように処理するかを自ら決定する.このような未定義の行為の文に対して私たちはできるだけ避けるべきです!
例4から、変数aの値を変更したくないことがわかります.それならconst_を定義します.castキーワード強制削除ポインタの定数性はいったい何の役に立つのでしょうか.次に次の例を見てみましょう.
例5:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
include
using namespace std;
const int * Search(const int * a, int n, int val);
int main()
{
int a[10] = {0,1,2,3,4,5,6,7,8,9};

int val = 5;

int *p;

p = const_cast(Search(a, 10, val));

if(p == NULL)

    cout<

}
const int * Search(const int * a, int n, int val)
{
int i;

for(i=0; i

}
例5では、a配列でval値を探し、見つかったらその値のアドレスを返し、見つからなかったらNULLを返す関数を定義した.関数Searchの戻り値はconstポインタであり、a配列でval値を見つけた場合、valのアドレスを返します.最も重要なのはa配列がmain関数ではconstではないため、戻り値の定数を除いてもa配列が変更される可能性がありますが、これは依然として安全です.
リファレンスの場合もconst_を使用できます.castは、例6に示すように定数性を強制的に除去する.
例6:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
include
using namespace std;
const int & Search(const int * a, int n, int val);
int main()
{
int a[10] = {0,1,2,3,4,5,6,7,8,9};
int val = 5;
int &p = const_cast
include
using namespace std;
class base
{
public :
void m(){cout<

};
class derived : public base
{
public:
void f(){cout<

};
int main()
{
derived * p;

p = new base;

p = static_cast(new base);

p->m();

p->f();

return 0;

}
この例では、baseクラスとderivedクラスの2つのクラスを定義します.この2つのクラスは継承関係を構成します.baseクラスではm関数が定義され、derivedクラスではf関数が定義されます.前述したマルチステートでは、派生クラスまたはベースクラスオブジェクトをベースクラスポインタで指していましたが、この例では異なります.
この例のメイン関数では、ベースクラスオブジェクトを指すときにエラーが発生し、コンパイルエラーが発生する派生クラスポインタが定義されています.
しかし、強制タイプ変換により、派生クラスポインタをベースクラスオブジェクトに向けることができます.p=static_cast
include
using namespace std;
class base
{
public :
void m(){cout<

};
class derived : public base
{
public:
void f(){cout<

};
int main()
{
derived * p;

p = new base;

p = dynamic_cast(new base);

p->m();

p->f();

return 0;

}
この例ではdynamic_を利用するcastは強制型変換を行うがbaseクラスには虚関数が存在しないためp=dynamic_cast
include
include
using namespace std;
class A
{
public:
virtual void f()
{
   cout<

};
class B:public A
{
public:

void f()

{

    cout<

};
class C
{
void pp()
{
  return;

}
};
int fun()
{
return 1;

}
int main()
{
A* a1=new B;//a1 A         B     

A* a2=new A;//a2 A         A     

B* b;

C* c;

b=dynamic_cast(a1);//   not null,      ,a1       B     ,       B     。

if(b==NULL)

{

    cout<(a2);//   null,      

if(b==NULL)

{

    cout<(a);//   null,      

if(c==NULL)

{

    cout<

}