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

旅途

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

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 旅途 閱讀(625) 評論(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>
            国产在线成人| 18成人免费观看视频| 亚洲一区二区三区高清| 99精品热视频| 国产精品一级| 久久午夜国产精品| 老司机精品福利视频| 亚洲黄网站在线观看| 亚洲人成网站精品片在线观看| 欧美成人资源网| 亚洲小说欧美另类社区| 午夜精品视频在线观看一区二区| 国产精品人人做人人爽人人添| 久久精品一区二区三区不卡牛牛| 久久精品国产精品亚洲| 亚洲狠狠婷婷| 亚洲影院在线| 亚洲国产经典视频| 一区二区三区波多野结衣在线观看| 国产精品色网| 亚洲高清色综合| 欧美性猛片xxxx免费看久爱| 久久九九国产精品怡红院| 久久只精品国产| 亚洲欧美国产不卡| 久久这里有精品15一区二区三区| 亚洲精品无人区| 先锋影院在线亚洲| 99精品福利视频| 性欧美办公室18xxxxhd| 9久草视频在线视频精品| 亚洲午夜精品17c| 亚洲黄色av一区| 亚洲欧美综合v| 中文久久精品| 久久午夜国产精品| 欧美一区2区三区4区公司二百| 欧美成人免费观看| 久久深夜福利免费观看| 欧美日韩国产成人在线免费| 久久亚洲电影| 国产欧美精品va在线观看| 亚洲欧洲日产国产网站| 狠狠色狠狠色综合| 夜夜嗨av色综合久久久综合网| 尤物网精品视频| 欧美一进一出视频| 亚洲欧美日韩一区在线| 欧美激情精品久久久久久黑人| 久久九九免费视频| 国产精品免费区二区三区观看| 亚洲精品在线看| 亚洲区中文字幕| 久久久精品欧美丰满| 久久福利视频导航| 国产美女精品视频免费观看| 日韩一级裸体免费视频| 亚洲免费观看| 欧美国产精品日韩| 亚洲国产毛片完整版| 91久久久亚洲精品| 看片网站欧美日韩| 亚洲成人在线网| 先锋资源久久| 午夜视频在线观看一区二区三区| 欧美日韩伦理在线| 日韩视频在线永久播放| 亚洲视频在线二区| 国产精品国产三级国产专区53| 一本色道久久综合亚洲91| 亚洲视频一二三| 欧美性色aⅴ视频一区日韩精品| 亚洲精品一区二区三区不| 亚洲区在线播放| 欧美日韩成人综合| 一区二区三区产品免费精品久久75 | 久久久久九九九九| 久久这里有精品15一区二区三区| 国语自产精品视频在线看8查询8| 久久精品盗摄| 欧美成人一区二免费视频软件| 亚洲国产日韩欧美在线动漫| 欧美成人精品福利| 亚洲美女网站| 久久国产日韩| 亚洲国产精品毛片| 欧美日韩一区二区精品| 亚洲视频在线一区| 久久这里有精品视频 | 欧美国产精品va在线观看| 亚洲黄色片网站| 亚洲一区三区视频在线观看 | 久久精品国产一区二区三区免费看| 久久综合给合| 一本色道久久综合亚洲91| 国产精品久久二区| 久久精品国产77777蜜臀| 欧美黄色一区| 欧美亚洲免费高清在线观看| 尤物在线精品| 国产精品热久久久久夜色精品三区| 久久er99精品| 亚洲日本一区二区| 久久久人成影片一区二区三区观看| 亚洲国产精品久久久久秋霞蜜臀| 国产精品igao视频网网址不卡日韩| 亚洲欧美文学| 亚洲精品综合精品自拍| 久久噜噜噜精品国产亚洲综合| 亚洲精品一区在线观看香蕉| 国产欧美日韩高清| 欧美区国产区| 久久天天综合| 亚洲欧美一区二区在线观看| 91久久国产自产拍夜夜嗨| 久久国产精品99国产精| 中国亚洲黄色| 亚洲精品免费在线播放| 国产日韩欧美一区二区三区在线观看 | 老牛嫩草一区二区三区日本| 亚洲在线视频观看| 亚洲人成网站影音先锋播放| 国产人成一区二区三区影院| 欧美日韩国产成人| 久久综合色天天久久综合图片| 亚洲综合视频一区| 99国内精品久久久久久久软件| 欧美国产精品v| 久久精品色图| 久久se精品一区精品二区| 亚洲一区二区精品在线| 亚洲人成网站色ww在线| 在线观看成人小视频| 国产欧美一区二区在线观看| 国产精品成人午夜| 欧美日韩国产综合新一区| 欧美电影在线观看| 美女精品一区| 欧美h视频在线| 蘑菇福利视频一区播放| 蜜臀av国产精品久久久久| 久久国产一区| 久久久久在线| 久久综合给合| 欧美mv日韩mv亚洲| 欧美国产综合视频| 欧美日韩国产123区| 欧美日韩网址| 国产精品人成在线观看免费| 国产精品视频一二| 国产伦精品一区二区三区免费| 国产乱码精品1区2区3区| 国产伦精品一区| 国产无一区二区| **欧美日韩vr在线| 亚洲七七久久综合桃花剧情介绍| 亚洲精品日本| 亚洲图片欧美一区| 欧美诱惑福利视频| 久久中文精品| 最新亚洲视频| 亚洲一区二区三区四区五区黄 | 亚洲一区精品在线| 欧美一区午夜精品| 裸体素人女欧美日韩| 欧美国产精品一区| 国产精品捆绑调教| 激情久久一区| 一本色道久久综合亚洲精品高清 | 亚洲电影观看| 宅男噜噜噜66国产日韩在线观看| 亚洲一区二区三区欧美| 久久精品国产亚洲aⅴ| 欧美刺激午夜性久久久久久久| 亚洲国产欧美一区二区三区丁香婷| 亚洲免费av片| 欧美在线在线| 欧美日韩国产综合视频在线| 国产欧美日韩视频一区二区三区| 尤物99国产成人精品视频| 99在线精品视频在线观看| 欧美在线播放| 91久久久精品| 欧美中文字幕在线观看| 欧美日韩国产探花| 精品91在线| 亚洲欧美日韩国产综合精品二区 | 欧美一区二区精品| 亚洲国产精品久久久久久女王| 亚洲免费视频成人| 欧美国产欧美亚洲国产日韩mv天天看完整 | 欧美中文字幕在线播放| 欧美日韩一区二区三区| 在线观看视频一区二区| 亚洲在线一区二区| 亚洲国产导航| 久久蜜桃精品| 国产中文一区| 欧美在线首页| 亚洲淫片在线视频|