[C/C++非一般的な構文プロパティ][dynamic_cast強制変換の利点]
3168 ワード
シーン:
1.C++がdynamic_を導入castというタイプの認識の強制変換は,エラーを認識するプログラムに有利であり,使えるところを提案し,変換エラー時に0を返したり異常を投げ出したりすることができ,Cの古い強制変換よりも
変換を実行してもタイプが間違っていないので、信頼性が高くなりません.このようなエラーが発生した場合、実際には見つけにくいからです.
メリット:
1.マルチステートのサブクラスの場合、親は処理インタフェースを提供できません.この場合、サブクラスに対して特別な処理を行うことができます.
2.dynamic_castは他の3つのcastよりも変換をチェックし、エラーが発生するとエラーが発生します.
注意:[20160113更新]
1.親はvirtualの生命を持つ方法または構造関数でなければならない.すなわちvtableがあり、そうでなければdynamic_castはエラーをコンパイルします.
知識点を追加:左と右(C++Primer 3 rdから抜粋)
//変数と文字定数にはストレージ領域があり、関連するタイプがあります.違いは、変数がアドレス可能なaddressable//各変数に2つの値が関連付けられていることです.//1.あるメモリアドレスにデータ値が格納されている場合、この値はオブジェクトの右値rvalue//are-valueとも呼ばれます.右値の意味は読み込まれた値read valueであり、文字定数と変数は右値として使用できます.//2.そのアドレス値、すなわちデータ値を格納メモリのアドレス変数と呼ばれる左値lvalueをell-value//と読むこともあるが、左値の意味は位置値location valueであり、文字定数は左値として使用できないと考えられる.
出力:
参考:『C++Primer 3 rd Edition』
1.C++がdynamic_を導入castというタイプの認識の強制変換は,エラーを認識するプログラムに有利であり,使えるところを提案し,変換エラー時に0を返したり異常を投げ出したりすることができ,Cの古い強制変換よりも
変換を実行してもタイプが間違っていないので、信頼性が高くなりません.このようなエラーが発生した場合、実際には見つけにくいからです.
メリット:
1.マルチステートのサブクラスの場合、親は処理インタフェースを提供できません.この場合、サブクラスに対して特別な処理を行うことができます.
2.dynamic_castは他の3つのcastよりも変換をチェックし、エラーが発生するとエラーが発生します.
注意:[20160113更新]
1.親はvirtualの生命を持つ方法または構造関数でなければならない.すなわちvtableがあり、そうでなければdynamic_castはエラーをコンパイルします.
1 error C2683: “dynamic_cast”:“CWindow” e:\work\sample\test_2005\test_2005\test_2005.cpp 37
知識点を追加:左と右(C++Primer 3 rdから抜粋)
//変数と文字定数にはストレージ領域があり、関連するタイプがあります.違いは、変数がアドレス可能なaddressable//各変数に2つの値が関連付けられていることです.//1.あるメモリアドレスにデータ値が格納されている場合、この値はオブジェクトの右値rvalue//are-valueとも呼ばれます.右値の意味は読み込まれた値read valueであり、文字定数と変数は右値として使用できます.//2.そのアドレス値、すなわちデータ値を格納メモリのアドレス変数と呼ばれる左値lvalueをell-value//と読むこともあるが、左値の意味は位置値location valueであり、文字定数は左値として使用できないと考えられる.
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <iostream>
#include <string>
#include <vector>
#include <typeinfo>
using namespace std;
class Bill
{
public:
virtual int GetBillNo()
{
return 0;
}
virtual time_t GetCreateDate()
{
time_t t;
time(&t);
return t;
}
virtual string GetBillName()
{
return string("Unknown.");
}
};
class DebtBill : public Bill
{
public:
virtual int GetBillNo()
{
return (int)this;
}
double GetDebtAmountDollar()
{
return (int)this + 4.4;
}
virtual string GetBillName()
{
return string("DebtBill.");
}
};
class OrderBill : public Bill
{
public:
virtual int GetBillNo()
{
return (int)this;
}
virtual string GetBillName()
{
return string("OrderBill.");
}
};
int main(int argc, char const *argv[])
{
std::vector<Bill*> v;
v.push_back(new DebtBill());
v.push_back(new OrderBill());
v.push_back(new OrderBill());
v.push_back(new DebtBill());
v.push_back(new OrderBill());
for (size_t i = 0; i < v.size(); ++i)
{
Bill* bill = v[i];
Bill& b2 = *bill;
cout << "BillNo: " << bill->GetBillNo()
<< " BillName: " << bill->GetBillName() << endl;
if (DebtBill* db = dynamic_cast<DebtBill*>(bill))
{
cout << "GetDebtAmountDollar: " << db->GetDebtAmountDollar() << endl;
}
// , , .
try
{
DebtBill& db2 = dynamic_cast<DebtBill&>(b2);
cout << "GetDebtAmountDollar2: " << db2.GetDebtAmountDollar() << endl;
}catch(std::bad_cast)
{
cout << "cast fail:" << endl;
}
}
return 0;
}
出力:
BillNo: 3870632 BillName: DebtBill.
GetDebtAmountDollar: 3.87064e+006
GetDebtAmountDollar2: 3.87064e+006
BillNo: 3870680 BillName: OrderBill.
cast fail:
BillNo: 3870664 BillName: OrderBill.
cast fail:
BillNo: 3870696 BillName: DebtBill.
GetDebtAmountDollar: 3.8707e+006
GetDebtAmountDollar2: 3.8707e+006
BillNo: 3870736 BillName: OrderBill.
cast fail:
参考:『C++Primer 3 rd Edition』