[C/C++非一般的な構文プロパティ][dynamic_cast強制変換の利点]


シーン:
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』