実行クラスの説明をに実装しました。実行時の説明は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);
}
}
私は混乱しています。 ':: WINERR_EXCEPTION'はどこに定義されていますか? –
'std :: exception'のコンストラクタに' szWhat'を 'char const *'を使って転送するのではなく、データメンバとして自分自身で格納するべきです。 http://msdn.microsoft.com/en-us/library/c4ts6d5a.aspx – ildjarn
@Robを参照してください:インクルードファイル "tstthrow.h"(私は提供しています)。 –