青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

旅途

如果想飛得高,就該把地平線忘掉

VC++中的異常與標準C++異常的差別和聯系(轉載自Microsoft Systems Journal 1999)

I can use two approaches for throwing an exception. The first approach is

														 CMyException myException;     throw myException;  
												
and the second is:
														 CMyException* pMyException = new CMyException();        throw pMyException;  
												
As far as I can figure out, the disadvantage of the first method is that the object is first constructed on the stack and then copied again to be passed from throw. The thing that I don't understand about the second approach is, who is responsible for freeing the CMyException object? MFC always uses the second approach, but none of the sample code that shows catching MFC exceptions has code to free the exception object. So, who's freeing it?

A Good question. The answer may surprise you. But first, let me give you the quick lowdown on exceptions, borrowed from Scott Meyers' excellent book, More Effective C++ (Addison-Wesley, 1995), Item #13. There are three ways you can throw/catch exceptions: by pointer, by value, or by reference.
If you throw/catch by pointer, you must allocate the exception object to throw, then delete it when you catch. This approach involves no extra copying, but there's a problem. If the exception was thrown using

														 static CMyException me(...); throw &me;
												
your program will [insert bad turn of events here] if the code that catches the exception tries to delete it. It may be fairly unusual to throw a static exception object, but it can be useful sometimes. The point is, there's no way the code that catches the exception can know whether the object was allocated from the heap or static memory, so there's no way for it to be absolutely sure whether to delete it. And it goes without saying that you can't throw a stack object using this method:
														 CMyException me(...);  throw &me;  
												
Everyone knows that a stack object no longer exists when control leaves the function containing it.
The second approach for throwing and catching exceptions is to throw/catch by value.
														 // throw code CMyException me; throw me;    // catch code  catch (CException e) {     // handle it }  
												
This avoids the allocation/destruction problem since the object is passed on the stack as a value, but at the cost of copying the object twice—once when the exception is thrown, and again when the exception is caught. You can avoid the first copy by writing
														 throw CMyException(...);  
												
which creates the CMyException directly on the return stack, but the second copy is still unavoidable.
Personally, I think the copy issue is no big deal since exceptions are by definition supposed to be, well, exceptional—that is, they don't happen often. For most applications, the time required to copy a few bytes is, to understate the case, insignificant. But there's a more serious problem with catching by value: it's called the slicing problem. I'm not talking about Ginsu knives, I'm talking about slicing objects.
In the previous code, e is declared as type CException, so that's what you get. Always. When the exception-throwing code throws a CMyException (derived from CException), the code that catches the exception gets a CException. The object loses all member data and functions added by CMyException; this information is sliced off. In general, C++ polymorphism only works through a pointer to an object, not an object itself. So in the case of MFC, if the code that catches the exception attempts to call the virtual functions CException::GetErrorMessage or ReportError, the compiler generates a call to CExeption::GetErrorMessage, not CMyException::GetErrorMessage—definitely not what you want.
The only way to fix this would be to declare e as CMyException.
														 catch (CMyException e) {     // handle it  }  
												
But this is obviously no solution; what happens when you introduce CMyException2? You have to modify every place that catches exceptions of this type, which rather defeats the whole purpose of polymorphism. For this reason, throwing exceptions by value is exceptionally grody.
As you may have guessed (you're so shrewd), I've saved the best option for last: throw/catch by reference. Using references, you can still throw the exception by value
														 throw CMyException(...);  
												
but now you use a reference to catch it:
														 catch (CException& e) {     // handle it  }  
												
Instead of copying the thrown object into a local variable, the compiler lets the code catching the exception manipulate the stack copy directly. There's no slicing problem. Throwing/catching exceptions by reference has the best of all worlds: no extra copying, you don't have to worry about who destroys the exception object (since it's always passed on the stack), and polymorphism is preserved. So from a purely theoretical perspective, references are the best way to do exceptions.
So much for theory. Now let's enter the world of MFC. MFC has its own exception mechanism that's based on C++, looks like C++, but isn't C++. Here you find TRY, END_TRY, CATCH, CATCH_ALL, AND_CATCH, END_CATCH, and other macros that resemble the C++ keywords.
Let's take a look at a vanilla TRY/CATCH sequence in MFC:
														 TRY     DoSomething(); CATCH (CMyException, e)     HandleBadKarma(); END_CATCH  
												
How does the compiler expand this? Don't bother going to the header files; I'll show you right now.
														 // TRY expands to: { AFX_EXCEPTION_LINK _afxExceptionLink; try {     DoSomething(); // CATCH expands to: } catch (CMyException* e)     { ASSERT_KINDOF(CMyException, e);       _afxExceptionLink.m_pException = e;        HandleBadKarma(); // END_CATCH expands to:    } }  
												
The first thing you'll notice is that MFC always catches exceptions by pointer (and throws them that way too, naturally). But what's that strange AFX_EXCEPTION_ LINK object, _afxExceptionLink? It's a little object that holds a pointer to the exception. When MFC catches the exception, it sets _afxExceptionLink.m_pException to point to the caught exception. And, as you might have guessed, the destructor AFX_EXCEPTION_LINK::~AFX_EXCEPTION_LINK deletes the object. It doesn't do it directly, but calls another function, AfxTryCleanup:
														 // called from ~AFX_EXCEPTION_LINK void AFXAPI AfxTryCleanup() {     AFX_EXCEPTION_CONTEXT* pContext         = AfxGetExceptionContext();     AFX_EXCEPTION_LINK* pLinkTop         = pContext->m_pLinkTop;       // delete current exception     if (pLinkTop->m_pException != NULL)         pLinkTop->m_pException->Delete();       // remove ourself from the top of the chain     pContext->m_pLinkTop = pLinkTop->m_pLinkPrev;  }  
												
The linked list of AFX_EXCEPTION_LINKs forms a stack. One global AFX_EXCEPTION_CONTEXT holds the pointer to the AFX_EXCEPTION_LINK on the top of the stack (m_pLinkTop). The AFX_EXCEPTION_LINK constructor adds itself to the stack; the destructor removes itself and deletes the exception object by calling m_pException->Delete. The upshot is this: MFC exceptions delete themselves as long as you use CATCH. Contrary to what you might expect, CException::Delete is not a virtual function; it's a normal member function that calls delete.
														 void CException::Delete() {     if (m_bAutoDelete > 0)        delete this;  }  
												
By default, exceptions are auto-deleting; that is, m_bAutoDelete is TRUE. If you don't want the catch code to delete your exception—for example, if it's a static object as in the previous examples—you can change m_bAutoDelete.
														 static CMyException staticex();  
												
														 staticex.m_bAutoDelete = FALSE; throw &staticex;  
												
Now CATCH code all over the world will not delete staticex. You can set m_bAutoDelete for a class or for an individual object, but you're forever locked into using the MFC CATCH, not the C++ catch. I won't bother to explain all the varieties of CATCH_ALL, AND_CATCH, THROW_LAST, and so on, since once you understand the idea of using AFX_EXCEPTION_LINK, you can pretty well figure out how they work.
Why does MFC do all this magic? Mostly for historical reasons. The Microsoft
? compiler was slow to support C++ exceptions using try/catch, so MFC provided its roll-yer-own implementation using TRY/CATCH, which was originally implemented using C setjmp/longjmp. For backward compatibility, you can still use this implementation by #defining the symbol _AFX_OLD_EXCEPTIONS before #including <afx.h>.
By now I've answered your question. The MFC sample code doesn't delete the exceptions because the TRY/CATCH code is so clever it generates code to delete them for you. But if you're reading the source code for MFC itself, you may be confused by code like this:
														 TRY {     DoSomething();  } CATCH_ALL(e) {     // handle it     DELETE_EXCEPTION(e);  }  
												
What's DELETE_EXCEPTION? I can't explain any better than the MFC source code itself, which contains the following comment in stdafx.h: "MFC does not rely on auto-delete semantics of the TRY/CATCH macros, therefore those macros are mapped to something closer to the native C++ exception handling mechanism when building MFC itself."
The stdafx.h used to build MFC contains its own entirely different definitions for TRY, CATCH, and so on; ones that map more or less directly to try/catch (with some ASSERTs thrown in for good measure). Since these internal TRY/CATCH implementations don't have the magic delete code, DELETE_EXCEPTION is required to manually call e->Delete.
So there are three possible implementations of TRY/CATCH: the "normal" implementation you get without doing anything (with all the magic auto-delete stuff using AFX_EXCEPTION_LINK); the "old" backward-compatible setjmp/longjmp implementation you get when you #define _AFX_OLD_EXCEPTIONS; and the implementation MFC uses internally, which requires DELETE_EXCEPTION to delete the exceptions. If all this makes you want to throw up your hands and pull out your hair, I can sympathize. It would be nice if the folks in Redmond rationalized their exception handling to map TRY/CATCH directly to try/catch, but I don't think it will happen since that might break lots of existing code.
So what should you do? If you call an MFC function that can throw an exception, you have no choice but to try to catch it. If you have old code that already uses TRY/CATCH, it probably works fine and you shouldn't do anything. But if you're writing new code, I would avoid TRY/CATCH entirely and stick with try/catch. Why? Three reasons: first, try/catch produces smaller code than the MFC macros (no hidden local objects with constructor/destructor calls); second, CATCH limits you to catching CException-derived exceptions; and finally, it just plain looks better to use real C++. TRY/CATCH was always a temporary kludge, so the sooner you forget it, the better. The only catch is, if you use try/catch, you have to remember to delete your exception object!
														 try{   CallSomeMFCFunction(); } catch( CException*e) { // recover e->Delete();
												
轉載自Microsoft Systems Journal 1999

posted on 2007-09-29 00:34 旅途 閱讀(611) 評論(0)  編輯 收藏 引用 所屬分類: C/C++

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲免费一级电影| 免费影视亚洲| 亚洲男女自偷自拍图片另类| 国产精品剧情在线亚洲| 亚洲欧美经典视频| 欧美一区二区三区男人的天堂| 国产欧美日韩一区| 欧美电影免费观看网站| 奶水喷射视频一区| 在线亚洲欧美| 亚洲欧美日韩综合国产aⅴ| 国产在线精品一区二区夜色| 久久亚洲精选| 欧美破处大片在线视频| 亚洲综合99| 久久久久久久久蜜桃| 亚洲人成网站在线播| 99精品99| 韩国成人精品a∨在线观看| 欧美1区视频| 欧美日韩成人综合在线一区二区| 亚洲午夜未删减在线观看| 亚洲欧美日韩天堂一区二区| 在线观看亚洲精品视频| 日韩视频一区| 伊人蜜桃色噜噜激情综合| 亚洲国产综合在线看不卡| 欧美系列一区| 欧美国产丝袜视频| 国产精品美女久久久| 免费短视频成人日韩| 国产精品超碰97尤物18| 另类天堂视频在线观看| 欧美日韩另类丝袜其他| 久久人人97超碰精品888| 欧美日本一道本在线视频| 老司机精品导航| 国产精品热久久久久夜色精品三区| 女人色偷偷aa久久天堂| 国产精品分类| 亚洲精品久久久一区二区三区| 国产日韩欧美电影在线观看| 亚洲精品五月天| 亚洲高清网站| 亚洲一区国产视频| 99热在这里有精品免费| 久久成人国产| 午夜视频一区二区| 欧美精品日韩一本| 农夫在线精品视频免费观看| 国产日韩欧美91| 亚洲综合第一页| 亚洲摸下面视频| 欧美少妇一区| 亚洲精品日韩精品| 日韩亚洲国产精品| 老巨人导航500精品| 久久国产精品色婷婷| 欧美日韩小视频| 亚洲国产欧美日韩精品| 激情欧美日韩一区| 久久精品亚洲一区二区| 欧美在现视频| 国产日韩欧美不卡在线| 亚洲在线免费视频| 午夜精品在线观看| 国产精品视频最多的网站| 亚洲一区影院| 欧美影院久久久| 国产亚洲欧美激情| 久久精品国产久精国产一老狼 | 精久久久久久久久久久| 亚洲欧美国产另类| 久久久不卡网国产精品一区| 国产一区二区三区在线观看免费视频 | 99精品福利视频| 亚洲视频在线一区| 国产精品高潮呻吟视频| 亚洲一区二区三区精品在线| 性欧美xxxx大乳国产app| 国产精品免费在线| 先锋影音久久久| 久久免费午夜影院| 亚洲国产日韩欧美| 欧美激情按摩| 亚洲一区视频在线观看视频| 久久精品最新地址| 亚洲国产精品电影在线观看| 欧美精品v国产精品v日韩精品| 91久久久一线二线三线品牌| 亚洲香蕉成视频在线观看| 欧美性色综合| 久久九九国产精品| 亚洲国产高清高潮精品美女| 亚洲视频一区| 国产视频在线观看一区二区三区| 久久久国产精品一区| 亚洲高清不卡| 性色av一区二区怡红| 亚洲国产精品成人va在线观看| 欧美国产日韩一区二区| 亚洲一区二区在线免费观看| 另类成人小视频在线| 在线视频日韩精品| 狠狠色丁香婷婷综合| 欧美黄色片免费观看| 亚洲欧美一区二区精品久久久 | 99精品视频免费| 国产一区二区三区高清在线观看| 久久夜色精品国产亚洲aⅴ| 一区二区久久| 欧美成人一品| 欧美在线观看一区| 一区二区国产精品| 亚洲第一精品夜夜躁人人爽| 国产精品蜜臀在线观看| 欧美激情 亚洲a∨综合| 久久久www成人免费无遮挡大片| 亚洲精品影视| 欧美福利精品| 久久综合久久久久88| 亚洲一二三区在线观看| 亚洲精品乱码久久久久久黑人| 国产一区二区丝袜高跟鞋图片 | 久久精品一区二区三区中文字幕| 国产精品99久久不卡二区| 亚洲高清影视| 欧美韩国日本一区| 噜噜噜91成人网| 久久婷婷色综合| 久久天堂国产精品| 久久国产视频网| 午夜欧美精品| 香蕉久久夜色精品| 亚洲综合色在线| 亚洲视频免费在线观看| 日韩视频在线一区| 亚洲人成在线观看网站高清| 亚洲国产精品久久91精品| 在线播放豆国产99亚洲| 国产一区欧美| 狠狠色综合播放一区二区| 国产视频精品网| 激情综合网激情| 亚洲第一综合天堂另类专| 激情成人在线视频| 亚洲第一精品福利| 亚洲国产91色在线| 亚洲人成人99网站| 一区二区日韩精品| 亚洲午夜国产成人av电影男同| 亚洲线精品一区二区三区八戒| 亚洲视频一区二区在线观看| 亚洲免费在线| 久久成人一区| 欧美成年人网站| 亚洲欧洲一二三| 在线综合视频| 欧美淫片网站| 麻豆精品精华液| 欧美巨乳在线| 国产精品一区二区黑丝| 国产亚洲一级高清| 亚洲欧洲日产国码二区| 夜色激情一区二区| 亚洲欧美日韩精品一区二区| 欧美与黑人午夜性猛交久久久| 久久综合伊人77777蜜臀| 欧美大片一区二区| 日韩午夜一区| 欧美在线视频在线播放完整版免费观看| 欧美伊人久久大香线蕉综合69| 久久久女女女女999久久| 欧美国产精品专区| 国产精品女人毛片| 在线看片日韩| 香蕉尹人综合在线观看| 久久亚洲欧洲| 9色精品在线| 久久久精品2019中文字幕神马| 欧美激情aⅴ一区二区三区| 国产精品无人区| avtt综合网| 久久综合图片| 亚洲女同性videos| 欧美激情一区二区| 国产一区视频网站| 中文欧美在线视频| 欧美 日韩 国产在线| 亚洲一级免费视频| 欧美极品欧美精品欧美视频| 国产在线播放一区二区三区| 日韩一区二区福利| 蜜臀va亚洲va欧美va天堂| 亚洲专区欧美专区| 一本色道久久精品| 久久九九全国免费精品观看| 亚洲国产专区校园欧美| 久久精品一级爱片| 国产精品一区二区三区免费观看 |