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

旅途

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

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>
            亚洲电影第三页| 欧美www视频| 亚洲午夜在线| 国产精品久久久久高潮| 欧美一区二区三区日韩| 午夜免费在线观看精品视频| 国产日韩欧美精品在线| 麻豆精品在线观看| 麻豆精品91| 亚洲小说春色综合另类电影| 亚洲中字在线| 在线成人激情黄色| 亚洲人成人77777线观看| 欧美性久久久| 久久久免费精品视频| 欧美承认网站| 亚洲欧美日韩精品久久亚洲区| 欧美在线播放一区二区| 亚洲欧洲精品一区二区三区| 一区二区三区四区国产| 一区二区在线视频| 日韩一级黄色片| 禁断一区二区三区在线| 日韩一级不卡| 精品69视频一区二区三区| 亚洲看片免费| 红桃视频国产一区| 99精品视频免费| 欲香欲色天天天综合和网| 99国产一区二区三精品乱码| 国产在线观看91精品一区| 亚洲国产精品小视频| 国产欧美日韩视频在线观看| 亚洲福利视频免费观看| 国产嫩草一区二区三区在线观看 | 欧美aa国产视频| 亚洲视频高清| 久久一二三四| 午夜精品久久久久久久99水蜜桃| 久久精品亚洲| 亚洲在线视频观看| 欧美77777| 久久精品国产亚洲精品| 欧美视频第二页| 欧美激情91| 国际精品欧美精品 | 午夜精品久久久久久久| 欧美成年人视频| 久久久久久久97| 国产精品卡一卡二| 亚洲美女在线视频| 亚洲每日更新| 老司机免费视频一区二区| 欧美亚洲一区二区在线观看| 欧美片网站免费| 亚洲激情视频在线播放| 在线精品一区二区| 久久久国产精品一区二区三区| 亚洲影院色无极综合| 欧美人与禽性xxxxx杂性| 亚洲高清成人| 亚洲国产专区校园欧美| 久久精品中文字幕一区| 久久久综合网| 狠狠噜噜久久| 久久视频精品在线| 另类图片国产| 在线欧美三区| 你懂的网址国产 欧美| 欧美激情一区二区在线 | 欧美国产精品久久| 亚洲大胆美女视频| 亚洲综合视频一区| 亚洲欧美在线一区二区| 国产精品日韩欧美一区| 亚洲综合日韩中文字幕v在线| 亚洲欧美国产毛片在线| 国产精品综合色区在线观看| 午夜精品福利视频| 久久综合电影一区| 亚洲国产乱码最新视频| 欧美久久影院| 亚洲欧美中文另类| 美女被久久久| 99视频精品全部免费在线| 欧美日韩视频专区在线播放| 在线视频亚洲| 玖玖综合伊人| 99在线精品视频在线观看| 欧美日韩精品欧美日韩精品一| 一本一本久久a久久精品综合麻豆| 亚洲欧美第一页| 激情视频一区| 欧美日产国产成人免费图片| 亚洲在线观看视频网站| 欧美成va人片在线观看| 亚洲视频一二三| 国产亚洲一区二区三区| 欧美jjzz| 欧美亚洲一区二区三区| 欧美国产精品v| 在线一区日本视频| 国产一区二区三区四区在线观看 | 亚洲伦伦在线| 久久疯狂做爰流白浆xx| 亚洲国产中文字幕在线观看| 国产精品久久久久高潮| 久久噜噜噜精品国产亚洲综合| 亚洲激情网址| 久久狠狠亚洲综合| 亚洲裸体俱乐部裸体舞表演av| 国产精品青草综合久久久久99| 久久久久女教师免费一区| 夜夜嗨av一区二区三区| 免费一区视频| 亚洲欧洲99久久| 亚洲精品五月天| 红桃av永久久久| 国产精品久久久久秋霞鲁丝| 蜜臀91精品一区二区三区| 亚洲女性裸体视频| 日韩视频在线免费观看| 欧美不卡一卡二卡免费版| 欧美伊人久久久久久久久影院 | 欧美午夜激情小视频| 久久久激情视频| 亚洲永久精品大片| 亚洲美女免费视频| 亚洲国产欧美精品| 免播放器亚洲一区| 久久久亚洲高清| 欧美在线亚洲综合一区| 亚洲午夜伦理| 亚洲视频1区| 一区二区不卡在线视频 午夜欧美不卡在 | 久久国产免费| 亚洲欧美日韩视频一区| 一区二区三区四区蜜桃| 亚洲精品国产拍免费91在线| 亚洲成人在线视频播放| 美女图片一区二区| 蜜臀va亚洲va欧美va天堂| 久久夜色精品亚洲噜噜国产mv| 欧美淫片网站| 久久久久久9999| 久久人人爽人人爽爽久久| 久久久久久免费| 久久精品一区二区| 久久亚洲精品中文字幕冲田杏梨 | 最新亚洲视频| 亚洲精选中文字幕| 亚洲深夜影院| 午夜日韩福利| 久久欧美肥婆一二区| 蜜桃精品一区二区三区| 欧美成人中文字幕| 91久久精品日日躁夜夜躁欧美 | 久久免费黄色| 狼人社综合社区| 欧美丰满少妇xxxbbb| 亚洲二区免费| 亚洲靠逼com| 亚洲天堂男人| 性做久久久久久久免费看| 久久国产日韩| 欧美成人综合| 国产精品久久久久秋霞鲁丝| 国产欧美一区二区三区视频| 狠狠久久亚洲欧美| 99一区二区| 欧美一区激情| 欧美成人久久| 亚洲素人一区二区| 久久久久国产免费免费| 欧美刺激午夜性久久久久久久| 欧美调教vk| 黑人操亚洲美女惩罚| 日韩视频一区| 久久精品91| 亚洲欧洲在线一区| 亚洲综合视频1区| 男女av一区三区二区色多| 欧美午夜电影在线观看| 今天的高清视频免费播放成人| 亚洲精品专区| 久久久久久尹人网香蕉| 亚洲精品网站在线播放gif| 欧美亚洲专区| 欧美日韩一区二区三区| 伊人影院久久| 午夜精品久久久久久99热| 欧美国产三级| 香蕉久久夜色精品国产| 欧美日韩视频不卡| 亚洲成人在线网| 久久精品日韩一区二区三区| 亚洲精品视频免费观看| 久久久久久一区| 国产日韩欧美综合一区| 一本色道久久综合|