2012-02-20 23 views
1

実行クラスの説明をに実装しました。実行時の説明はGetLastError()です!MSVC std :: exceptionは標準に準拠していませんか?

期待通りに機能しました。 その後、私は不要な割り当てを取り除きたいと思っていました。 私は、what()によって返されるconst char*を受け取って格納する中間クラスを実装しました。

しかし、interim_exceptionクラスを使用すると、std :: exceptionのMSVC(C++ 11開発者プレビュー)の実装では、what()の代わりにstd::exceptionの基本メンバーメンバー変数を使用して説明文字列をコピーします。 となり、what()という戻り値として"unknown exception"が返されます。

exception& operator=(const exception& rhs) noexcept; 
    Effects: Copies an exception object. 
    Postcondition: If *this and rhs both have dynamic type exception then strcmp(what(), rhs.what()) shall equal 0. 

単語事後条件でダイナミック(私のinterim_exceptionの説明は、動的に割り当てられていない)で行うには、この何かを持っているか、これは単に間違って実装したものです:

標準はが言いますか?

MSVCのはstd ::例外::演算子=():

_EXCEPTION_INLINE exception& __CLR_OR_THIS_CALL exception::operator=(const exception& _That) 
    { 
    if (this != &_That) 
     { 
     _Tidy(); // resets members 

     if (_That._Mydofree) // NB. This prevents my intentions (evals to false) 
      { 
      _Copy_str(_That._Mywhat); 
      } 
     else 
      { 
      _Mywhat = _That._Mywhat; 
      } 
     } 

    return *this; 
    } 

私のコード:

//////////////////////////////////////////////////////////////////////////////// 
// file : TstThrow.h 
// purpose : implementation of class WINERR_EXCEPTION 
//////////////////////////////////////////////////////////////////////////////// 
// 

#include <windows.h> 
#include <exception> 
#include <stdexcept> 

//////////////////////////////////////////////////////////////////////////////// 

namespace 
{ 
    // class interim_exception to avoid unnecessary allocations 
    class interim_exception 
     : public std::exception 
    { 
    public: 
     // override member : what() const 
    const char * what() const 
    //_EXCEPTION_INLINE virtual const char * __CLR_OR_THIS_CALL what() const 
    { return m_What; } 

     interim_exception(const char* szWhat) 
      :m_What(szWhat ? szWhat : "") {} 

    private: 
     const char* m_What; 

    }; 
} 

//////////////////////////////////////////////////////////////////////////////// 

class WINERR_EXCEPTION 
    : public std::exception 
{ 
public: 
    DWORD ErrNo() const { return m_ErrNo; } 

public: 
    explicit WINERR_EXCEPTION (DWORD dwErrNo); 

    inline exception& operator= (const exception& that) 
    { 
     exception::operator= (that); 
     return (*this); 
    } 

    inline exception& operator= (const char* szWhat) 
    { 
     operator= (std::exception(szWhat)); /* this works OK */ 
     // exception::operator= (std::exception(szWhat)); /* this works OK */ 
     // exception::operator= (interim_exception(szWhat)); /* this doesn't work */ 
     // operator= (interim_exception(szWhat)); /* this doesn't work */ 
     return (*this); 
    } 

private: 
    DWORD m_ErrNo; 

}; 

//////////////////////////////////////////////////////////////////////////////// 


WINERR_EXCEPTION::WINERR_EXCEPTION (DWORD dwErrNo) 
    :m_ErrNo (dwErrNo) //exception("") , 
{ 
    DWORD dwFrmtFlags (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER); 
    dwFrmtFlags |= FORMAT_MESSAGE_IGNORE_INSERTS; 
    dwFrmtFlags |= FORMAT_MESSAGE_MAX_WIDTH_MASK; // no newlines 

    LPSTR pBuffer (nullptr); 
    if (! ::FormatMessageA(dwFrmtFlags ,nullptr 
          ,dwErrNo ,0 ,(LPSTR)&pBuffer ,0 ,nullptr)) 
    { 
     dwErrNo = GetLastError(); 
     if (dwErrNo == ERROR_MR_MID_NOT_FOUND) 
      operator= (WINERR_EXCEPTION(dwErrNo).what()); 
     else 
      operator= ("Substituted Error Message :\n\t" 
         "Could not allocate buffer for ORIGINAL Error Message\n"); 
    } 
    else 
    { 
     operator= (pBuffer); 
     LocalFree(pBuffer); 
    } 
} 

//////////////////////////////////////////////////////////////////////////////// 

私のテスト:

void  TstThrow() 
{ 
    for (DWORD dwErr = ERROR_SUCCESS; dwErr < 200; ++dwErr) 
    { 
     SetLastError(dwErr); 
     try 
     { 
      throw ::WINERR_EXCEPTION(GetLastError()); 
     } 
     catch (const ::WINERR_EXCEPTION& werr) 
     { 
      ::WINERR_EXCEPTION err (werr); // test for copying of object ! 

      std::cout << std::setw(4) << werr.ErrNo() << " :"<< werr.what() << std::endl; 
     } 

     if ((dwErr % 100) == 0) 
      Sleep(1500); 
    } 
} 
+0

私は混乱しています。 ':: WINERR_EXCEPTION'はどこに定義されていますか? –

+1

'std :: exception'のコンストラクタに' szWhat'を 'char const *'を使って転送するのではなく、データメンバとして自分自身で格納するべきです。 http://msdn.microsoft.com/en-us/library/c4ts6d5a.aspx – ildjarn

+0

@Robを参照してください:インクルードファイル "tstthrow.h"(私は提供しています)。 –

答えて

3

二つのオブジェクト「の両方がダイナミック持ちます両方のオブジェクトの動的タイプがexceptionであり、例外のサブタイプでない場合は、タイプexceptionと入力します。ダイナミックタイプはWINERR_EXCEPTIONであり、exceptionではないため、事後条件は該当しません。

あなたはwhat()std::exception()が提供するデフォルト以外の何かを返したい場合は、それを自分で上書きする、またはそのような<stdexcept>で定義された例外の種類として、それを上書きします何かを継承するかがあります。 (少なくともStandard C++のケースだが、std::exceptionへのMicrosoftの拡張がどのように機能するのか正確には分からないので、コメントできない。)

+0

動的なタイプ(1.3.7&1.3.8)の2つの定義があり、私の場合は1.3.8が適用されていると考えていたので、少し混乱しています。 –

+0

@Edwin:参照は左辺値なので、いいえ、1.3.7が適用されます。 1.3.8はオブジェクト自体にのみ適用されます。その場合、動的型と静的型は同じです。 –

+0

あなたが編集したことについて正しい(間違った値) –

関連する問題