5

静的チェック ツールは、以下のコードで違反を示します。

class CSplitFrame : public CFrameWnd  
...
class CVsApp : public CWinApp
CWnd* CVsApp::GetSheetView(LPCSTR WindowText)
{
 CWnd* pWnd = reinterpret_cast<CSplitFrame*>(m_pMainWnd)->m_OutputBar.GetChildWnd(WindowText);
 return pWnd;
}

エラー メッセージ:クラス 'CSplitFrame' は、クラス 'CWnd' を継承しています

説明:継承階層を下にキャストしないようにします。このルールは、基本クラス ポインターからサブクラス ポインターへのキャストを検出します。

利点:継承階層の下位へのキャストを許可すると、メンテナンスの問題が発生し、基底クラスからの下位キャストは常に違法になります。

参考文献:

  1. Scott Meyers、「効果的な C++: プログラムと設計を改善するための 50 の具体的な方法」、第 2 版、Addison-Wesley、(C) 2005 Pearson Education, Inc.、章:「継承とオブジェクト指向設計」、項目 39
  2. JOINT STRIKE FIGHTER、AIR VEHICLE、C++ コーディング標準、第 4.23 章型変換、AV ルール 178

基本クラスのポインターからサブクラスのポインターにキャスト ダウンしないことは良い習慣だと思いますか? なぜ、いつこのルールに従う必要があるのですか?

4

4 に答える 4

10

reinterpret_castコーディング標準や OOP 理論に関係なく、ここでは確かに悪い考えです。dynamic_castまたはboost::polymorphic_downcastでなければなりません。

Effective C++ の第 39 章に関しては、複数の異なる型にダウンキャストする必要があり、潜在的なエラーの戻り値をチェックする必要があるために発生するメンテナンスの問題に集中しておりdynamic_cast、コードに複数の分岐が発生します。

重要なことは、ダウンキャストが常に導く if-then-else スタイルのプログラミングは、仮想関数の使用よりもはるかに劣っており、本当に代替手段がない状況のために取っておくべきです。

于 2010-09-30T16:00:58.140 に答える
4

MFC でのダウンキャストの例をいくつか見てみましょう。

CWnd* からの CButton*

CWnd* wnd = GetDlgItem(IDC_BUTTON_ID);
CButton* btn = dynamic_cast<CButton*>(wnd);

CFrameWnd* からの CChildWnd*

CChildWnd * pChild = ((CSplitFrame*)(AfxGetApp()->m_pMainWnd))->GetActive();

実際、MFC の設計にはいくつかの制限があります。

CWnd は MFC のすべてのウィンドウ クラスの基本機能を提供するため、View、Dialog、Button などの基本クラスとしても機能します。

ダウンキャストを回避したい場合は、おそらく MFC ハッカーが CWnd をより少ない断片に分割する必要がありますか?

ここで、違反をどのように解決するかという別の質問に移ります。私の謙虚な意見は、安全なダウンキャストを使用して、安全でないダウンキャストを回避しようとすることです。

Parent *pParent = new Parent;
Parent *pChild = new Child;

Child *p1 = static_cast<Child*>(pParent);   // Unsafe downcasting:it assigns the address of a base-class object (Parent) to a derived class (Child) pointer
Parent *p2 = static_cast<Child*>(pChild);   // Safe downcasting:it assigns the address of a derived-class object to a base-class pointer

違反がまだ存在していても、安全なダウンキャストを使用するための良い習慣として役立ちます。特定の説明で違反を抑制します。

有用なリファレンスの一部:
http://support.microsoft.com/kb/108587
http://blog.csdn.net/ecai/archive/2004/06/26/27458.aspx
http://www.codeproject. com/KB/mcpp/castingbasics.aspx
http://www.bogotobogo.com/cplusplus/upcasting_downcasting.html

最後に、皆様からの様々な有益なご回答をありがとうございました。
彼らは確かに非常に役に立ちます。

于 2010-10-06T02:53:04.310 に答える
0

クラスポインタのダウンキャストは、一般に、適切に設計されたOOPコードでは絶対に避けなければならないものです。それでも、特にクライアントコードでそのようなキャストを要求するように設計された他のライブラリ/コードを使用している場合は、そのようなキャストが必要になることがあります。MFCはそのようなライブラリの一例です。

ダウンキャストが本当に必要な場合は、を使用して実行しないでくださいreinterpret_cast。キャストを実行する適切な方法は、またはのいずれdynamic_caststatic_castです。

コードでダウンキャストに使用reinterpret_castされるCスタイルのキャストを見て、それをC ++スタイルのキャストに変換することを決定した場合、そのようなコンテキストでのCスタイルのキャストがと同等であると誤って想定することがよくありreinterpret_castます。実際には、親子タイプのペアに任意の方向に適用されるCスタイルのキャストはstatic_cast、いくつかの追加の特典を使用する場合と同等です(Cスタイルのキャストはアクセス保護を突破する可能性があります)。したがって、繰り返しになりますが、この目的でCスタイルのキャストを使用することは誤りですが、適切なC ++置換はreinterpret_cast、ではなくdynamic_cast、またはstatic_castです。

于 2010-10-03T23:08:38.583 に答える
0

とにかくキャストを実行することが実際に必要であるように、または少なくともあなたがそれをしているように、私には見えません。関数はを返す必要があるCWndため、までキャストする必要はありませんCSplitFrame

私はそれがまたは同様GetChildWndのものを返すことを期待していました。CWnd*なぜあなたは次のようなものを書くことができないのですか?

CWnd* CVsApp::GetSheetView(LPCSTR WindowText)
{
   return m_pMainWnd->m_OutputBar.GetChildWnd(WindowText);
}
于 2010-10-03T22:44:53.700 に答える