锘??xml version="1.0" encoding="utf-8" standalone="yes"?> 浣嶈繍綆楃鏈夛細&(鎸変綅涓?銆亅(鎸変綅鎴?銆乛(鎸変綅寮傛垨)銆亊 (鎸変綅鍙栧弽)銆? 浣嶈繍綆楃鐨勪竴浜涚畝鍗曞簲鐢? 鎸変綅鎴栬繍綆楃殑鍏稿瀷鐢ㄦ硶鏄皢涓涓綅涓蹭俊鎭殑鏌愬嚑浣嶇疆鎴?銆傚灝嗚鑾峰緱鏈鍙?涓?錛屽叾浠栦綅涓庡彉閲廽鐨勫叾浠栦綅鐩稿悓錛屽彲鐢ㄩ昏緫鎴栬繍綆?17|j 鎸変綅寮傛垨榪愮畻鐨勫吀鍨嬬敤娉曟槸姹備竴涓綅涓蹭俊鎭殑鏌愬嚑浣嶄俊鎭殑鍙嶃傚嬈叉眰鏁村瀷鍙橀噺j鐨勬渶鍙?浣嶄俊鎭殑鍙嶏紝鐢ㄩ昏緫寮傛垨榪愮畻017^j錛屽氨鑳芥眰寰梛鏈鍙?浣嶇殑淇℃伅鐨勫弽,鍗沖師鏉ヤ負1鐨勪綅錛岀粨鏋滄槸0,鍘熸潵涓?鐨勪綅錛岀粨鏋滄槸1銆?浜ゆ崲涓や釜鍊鹼紝涓嶇敤涓存椂鍙橀噺,鍋囧a=3,b=4銆傛兂灝哸鍜宐鐨勫間簰鎹紝鍙互鐢ㄤ互涓嬭祴鍊艱鍙ュ疄鐜幫細 鍙栧弽榪愮畻甯哥敤鏉ョ敓鎴愪笌緋葷粺瀹炵幇鏃犲叧鐨勫父鏁般傚瑕佸皢鍙橀噺x鏈浣?浣嶇疆鎴?錛屽叾浣欎綅涓嶅彉錛屽彲鐢ㄤ唬鐮亁 = x & ~077瀹炵幇銆備互涓婁唬鐮佷笌鏁存暟x鐢?涓瓧鑺傝繕鏄敤4涓瓧鑺傚疄鐜版棤鍏熾? 浣嶈繍綆楃敤鏉ュ浣嶄覆淇℃伅榪涜榪愮畻錛屽緱鍒頒綅涓蹭俊鎭粨鏋溿傚浠ヤ笅浠g爜鑳藉彇涓嬫暣鍨嬪彉閲弅鐨勪綅涓蹭俊鎭殑鏈鍙寵竟涓?鐨勪俊鎭綅錛?(k-1)^k) & k銆? 瀵逛簬甯︾鍙風殑鏁版嵁錛屽鏋滅Щ浣嶅墠絎﹀彿浣嶄負0(姝f暟)錛屽垯宸︾涔熸槸鐢?琛ュ厖錛涘鏋滅Щ浣嶅墠絎﹀彿浣嶄負1(璐熸暟)錛屽垯宸︾鐢?鎴栫敤1琛ュ厖錛屽彇鍐充簬璁$畻鏈虹郴緇熴傚浜庤礋鏁板彸縐伙紝縐扮敤0 琛ュ厖鐨勭郴緇熶負“閫昏緫鍙崇Щ”錛岀敤1琛ュ厖鐨勭郴緇熶負“綆楁湳鍙崇Щ”銆備互涓嬩唬鐮佽兘璇存槑璇昏呬笂鏈虹殑緋葷粺鎵閲囩敤鐨勫彸縐繪柟娉曪細 縐諱綅榪愮畻涓庝綅榪愮畻緇撳悎鑳藉疄鐜拌澶氫笌浣嶄覆榪愮畻鏈夊叧鐨勫鏉傝綆椼傝鍙橀噺鐨勪綅鑷彸鑷沖乏欏哄簭緙栧彿錛岃嚜0浣嶈嚦15浣嶏紝鏈夊叧鎸囧畾浣嶇殑琛ㄨ揪寮忔槸涓嶈秴榪?5鐨勬鏁存暟銆備互涓嬪悇浠g爜鍒嗗埆鏈夊畠浠彸杈規敞閲婃墍紺虹殑鎰忎箟錛?br> (1) 鍒ゆ柇int鍨嬪彉閲廰鏄鏁拌繕鏄伓鏁?灝ゅ叾鏄澶ф暟鐨勫垽鏂?br> a&1 == 0 鍋舵暟
鎽樿嚜錛?a href="http://www.shnenglu.com/pengkuny/archive/2007/04/21/22551.html">http://www.shnenglu.com/pengkuny/archive/2007/04/21/22551.html
浼樺厛綰т粠楂樺埌浣庯紝渚濇涓簙銆?amp;銆乛銆亅錛?
鎸変綅涓庤繍綆楁湁涓ょ鍏稿瀷鐢ㄦ硶錛屼竴鏄彇涓涓綅涓蹭俊鎭殑鏌愬嚑浣嶏紝濡備互涓嬩唬鐮佹埅鍙杧鐨勬渶浣?浣嶏細x & 0177銆備簩鏄鏌愬彉閲忎繚鐣欐煇鍑犱綅錛屽叾浣欎綅緗?錛屽浠ヤ笅浠g爜璁﹛鍙繚鐣欐渶浣?浣嶏細x = x & 077銆?/p>
a=a^b; b=b^a; a=a^b;
褰撲袱涓暱搴︿笉鍚岀殑鏁版嵁榪涜浣嶈繍綆楁椂(渚嬪long鍨嬫暟鎹笌int鍨嬫暟鎹?錛屽皢涓や釜榪愮畻鍒嗛噺鐨勫彸绔榻愯繘琛屼綅榪愮畻銆傚鏋滅煭鐨勬暟涓烘鏁幫紝楂樹綅鐢?琛ユ弧錛涘鏋滅煭鐨勬暟涓鴻礋鏁幫紝楂樹綅鐢?琛ユ弧銆傚鏋滅煭鐨勪負鏃犵鍙鋒暣鏁幫紝鍒欓珮浣嶆繪槸鐢?琛ユ弧銆?/p>
printf("%d\n\n\n", -2>>4);
鑻ヨ緭鍑虹粨鏋滀負-1錛屾槸閲囩敤綆楁湳鍙崇Щ錛涜緭鍑虹粨鏋滀負涓涓ぇ鏁存暟錛屽垯涓洪昏緫鍙崇Щ銆?/p>
a&1 == 1 濂囨暟
(2) 鍙杋nt鍨嬪彉閲廰鐨勭k浣?(k=0,1,2……sizeof(int))
a>>k&1
(3) 灝唅nt鍨嬪彉閲廰鐨勭k浣嶆竻0
a=a&~(1<<k)
(4) 灝唅nt鍨嬪彉閲廰鐨勭k浣嶇疆1
a=a|(1<<k)
(5) int鍨嬪彉閲忓驚鐜乏縐籯嬈?br> a=a<<k|a>>16-k (璁緎izeof(int)=16)
(6) int鍨嬪彉閲廰寰幆鍙崇Щk嬈?br> a=a>>k|a<<16-k (璁緎izeof(int)=16)
(7) 瀹炵幇鏈浣巒浣嶄負1錛屽叾浣欎綅涓?鐨勪綅涓蹭俊鎭?
~錛垀0 << n錛?
(8)鎴彇鍙橀噺x鑷猵浣嶅紑濮嬬殑鍙寵竟n浣嶇殑淇℃伅:
(x >> (1+p-n)) & ~(~0 << n)
(9)鎴彇old鍙橀噺絎瑀ow浣嶏紝騫跺皢璇ヤ綅淇℃伅瑁呴厤鍒板彉閲弉ew鐨勭15-k浣?br> new |= ((old >> row) & 1) << (15 – k)
(10)璁緎涓嶇瓑浜庡叏0錛屼唬鐮佸鎵炬渶鍙寵竟涓?鐨勪綅鐨勫簭鍙穓:
for(j = 0; ((1 << j) & s) == 0; j++) ;
鏈変簺鐢ㄦ硶榪樻湭鑰冭瘉
]]>
闄堢殦
鍓嶈█
C++涓殑铏氬嚱鏁扮殑浣滅敤涓昏鏄疄鐜頒簡澶氭佺殑鏈哄埗銆傚叧浜庡鎬侊紝綆鑰岃█涔嬪氨鏄敤鐖剁被鍨嬪埆鐨勬寚閽堟寚鍚戝叾瀛愮被鐨勫疄渚嬶紝鐒跺悗閫氳繃鐖剁被鐨勬寚閽堣皟鐢ㄥ疄闄呭瓙綾葷殑鎴愬憳鍑芥暟銆傝繖縐嶆妧鏈彲浠ヨ鐖剁被鐨勬寚閽堟湁“澶氱褰㈡?#8221;錛岃繖鏄竴縐嶆硾鍨嬫妧鏈傛墍璋撴硾鍨嬫妧鏈紝璇寸櫧浜嗗氨鏄瘯鍥句嬌鐢ㄤ笉鍙樼殑浠g爜鏉ュ疄鐜板彲鍙樼殑綆楁硶銆傛瘮濡傦細妯℃澘鎶鏈紝RTTI鎶鏈紝铏氬嚱鏁版妧鏈紝瑕佷箞鏄瘯鍥懼仛鍒板湪緙栬瘧鏃跺喅璁紝瑕佷箞璇曞浘鍋氬埌榪愯鏃跺喅璁?/p>
鍏充簬铏氬嚱鏁扮殑浣跨敤鏂規硶錛屾垜鍦ㄨ繖閲屼笉鍋氳繃澶氱殑闃愯堪銆傚ぇ瀹跺彲浠ョ湅鐪嬬浉鍏崇殑C++鐨勪功綾嶃傚湪榪欑瘒鏂囩珷涓紝鎴戝彧鎯充粠铏氬嚱鏁扮殑瀹炵幇鏈哄埗涓婇潰涓哄ぇ瀹?涓涓竻鏅扮殑鍓栨瀽銆?/p>
褰撶劧錛岀浉鍚岀殑鏂囩珷鍦ㄧ綉涓婁篃鍑虹幇榪囦竴浜涗簡錛屼絾鎴戞繪劅瑙夎繖浜涙枃绔犱笉鏄緢瀹規槗闃呰錛屽ぇ孌靛ぇ孌電殑浠g爜錛屾病鏈夊浘鐗囷紝娌℃湁璇︾粏鐨勮鏄庯紝娌℃湁姣旇緝錛屾病鏈変婦涓鍙嶄笁銆備笉鍒╀簬瀛︿範鍜岄槄璇伙紝鎵浠ヨ繖鏄垜鎯沖啓涓嬭繖綃囨枃绔犵殑鍘熷洜銆備篃甯屾湜澶у澶氱粰鎴戞彁鎰忚銆?/p>
璦褰掓浼狅紝璁╂垜浠竴璧瘋繘鍏ヨ櫄鍑芥暟鐨勪笘鐣屻?/p>
铏氬嚱鏁拌〃
瀵笴++ 浜嗚В鐨勪漢閮藉簲璇ョ煡閬撹櫄鍑芥暟錛圴irtual Function錛夋槸閫氳繃涓寮犺櫄鍑芥暟琛紙Virtual Table錛夋潵瀹炵幇鐨勩傜畝縐頒負V-Table銆傚湪榪欎釜琛ㄤ腑錛屼富鏄涓涓被鐨勮櫄鍑芥暟鐨勫湴鍧琛紝榪欏紶琛ㄨВ鍐充簡緇ф壙銆佽鐩栫殑闂錛屼繚璇佸叾瀹圭湡瀹炲弽搴斿疄闄呯殑鍑芥暟銆傝繖鏍鳳紝鍦ㄦ湁铏氬嚱鏁扮殑綾葷殑瀹炰緥涓繖涓〃琚垎閰嶅湪浜嗚繖涓疄渚嬬殑鍐呭瓨涓紝鎵浠ワ紝褰撴垜浠敤鐖剁被鐨勬寚閽堟潵鎿嶄綔涓涓瓙綾葷殑鏃跺欙紝榪欏紶铏氬嚱鏁拌〃灝辨樉寰楃敱涓洪噸瑕佷簡錛屽畠灝卞儚涓涓湴鍥句竴鏍鳳紝鎸囨槑浜嗗疄闄呮墍搴旇璋冪敤鐨勫嚱鏁般?/p>
榪欓噷鎴戜滑鐫閲嶇湅涓涓嬭繖寮犺櫄鍑芥暟琛ㄣ侰++鐨勭紪璇戝櫒搴旇鏄繚璇佽櫄鍑芥暟琛ㄧ殑鎸囬拡瀛樺湪浜庡璞″疄渚嬩腑鏈鍓嶉潰鐨勪綅緗紙榪欐槸涓轟簡淇濊瘉鍙栧埌铏氬嚱鏁拌〃鐨勬湁鏈楂樼殑鎬ц兘鈥斺斿鏋滄湁澶氬眰緇ф壙鎴栨槸澶氶噸緇ф壙鐨勬儏鍐典笅錛夈?榪欐剰鍛崇潃鎴戜滑閫氳繃瀵硅薄瀹炰緥鐨勫湴鍧寰楀埌榪欏紶铏氬嚱鏁拌〃錛岀劧鍚庡氨鍙互閬嶅巻鍏朵腑鍑芥暟鎸囬拡錛屽茍璋冪敤鐩稿簲鐨勫嚱鏁般?/p>
鍚垜鎵簡閭d箞澶氾紝鎴戝彲浠ユ劅瑙夊嚭鏉ヤ綘鐜板湪鍙兘姣斾互鍓嶆洿鍔犳檿澶磋漿鍚戜簡銆?娌″叧緋伙紝涓嬮潰灝辨槸瀹為檯鐨勪緥瀛愶紝鐩鎬俊鑱槑鐨勪綘涓鐪嬪氨鏄庣櫧浜嗐?/p>
鍋囪鎴戜滑鏈夎繖鏍風殑涓涓被錛?/p>
class Base {
public:
virtual void f() { cout << "Base::f" << endl; }
virtual void g() { cout << "Base::g" << endl; }
virtual void h() { cout << "Base::h" << endl; }
};
鎸夌収涓婇潰鐨勮娉曪紝鎴戜滑鍙互閫氳繃Base鐨勫疄渚嬫潵寰楀埌铏氬嚱鏁拌〃銆?涓嬮潰鏄疄闄呬緥紼嬶細
typedef void(*Fun)(void);
Base b;
Fun pFun = NULL;
cout << "铏氬嚱鏁拌〃鍦板潃錛? << (int*)(&b) << endl;
cout << "铏氬嚱鏁拌〃 鈥?絎竴涓嚱鏁板湴鍧錛? << (int*)*(int*)(&b) << endl;
// Invoke the first virtual function
pFun = (Fun)*((int*)*(int*)(&b));
pFun();
瀹為檯榪愯緇忔灉濡備笅錛?Windows XP+VS2003, Linux 2.6.22 + GCC 4.1.3)
铏氬嚱鏁拌〃鍦板潃錛?012FED4
铏氬嚱鏁拌〃 鈥?絎竴涓嚱鏁板湴鍧錛?044F148
Base::f
閫氳繃榪欎釜紺轟緥錛屾垜浠彲浠ョ湅鍒幫紝鎴戜滑鍙互閫氳繃寮鴻鎶?amp;b杞垚int *錛屽彇寰楄櫄鍑芥暟琛ㄧ殑鍦板潃錛岀劧鍚庯紝鍐嶆鍙栧潃灝卞彲浠ュ緱鍒扮涓涓櫄鍑芥暟鐨勫湴鍧浜嗭紝涔熷氨鏄疊ase::f()錛岃繖鍦ㄤ笂闈㈢殑紼嬪簭涓緱鍒頒簡楠岃瘉錛堟妸int* 寮哄埗杞垚浜嗗嚱鏁版寚閽堬級銆傞氳繃榪欎釜紺轟緥錛屾垜浠氨鍙互鐭ラ亾濡傛灉瑕佽皟鐢˙ase::g()鍜孊ase::h()錛屽叾浠g爜濡備笅錛?/p>
(Fun)*((int*)*(int*)(&b)+0); // Base::f()
(Fun)*((int*)*(int*)(&b)+1); // Base::g()
(Fun)*((int*)*(int*)(&b)+2); // Base::h()
榪欎釜鏃跺欎綘搴旇鎳備簡鍚с備粈涔堬紵榪樻槸鏈夌偣鏅曘備篃鏄紝榪欐牱鐨勪唬鐮佺湅鐫澶貢浜嗐傛病闂錛岃鎴戠敾涓浘瑙i噴涓涓嬨傚涓嬫墍紺猴細
娉ㄦ剰錛氬湪涓婇潰榪欎釜鍥句腑錛屾垜鍦ㄨ櫄鍑芥暟琛ㄧ殑鏈鍚庡鍔犱簡涓涓粨鐐癸紝榪欐槸铏氬嚱鏁拌〃鐨勭粨鏉熺粨鐐癸紝灝卞儚瀛楃涓茬殑緇撴潫絎?#8220;\0”涓鏍鳳紝鍏舵爣蹇椾簡铏氬嚱鏁拌〃鐨勭粨鏉熴傝繖涓粨鏉熸爣蹇楃殑鍊煎湪涓嶅悓鐨勭紪璇戝櫒涓嬫槸涓嶅悓鐨勩傚湪WinXP+VS2003涓嬶紝榪欎釜鍊兼槸NULL銆傝屽湪Ubuntu 7.10 + Linux 2.6.22 + GCC 4.1.3涓嬶紝榪欎釜鍊兼槸濡傛灉1錛岃〃紺鴻繕鏈変笅涓涓櫄鍑芥暟琛紝濡傛灉鍊兼槸0錛岃〃紺烘槸鏈鍚庝竴涓櫄鍑芥暟琛ㄣ?/p>
涓嬮潰錛屾垜灝嗗垎鍒鏄?#8220;鏃犺鐩?#8221;鍜?#8220;鏈夎鐩?#8221;鏃剁殑铏氬嚱鏁拌〃鐨勬牱瀛愩傛病鏈夎鐩栫埗綾葷殑铏氬嚱鏁版槸姣棤鎰忎箟鐨勩傛垜涔嬫墍浠ヨ璁茶堪娌℃湁瑕嗙洊鐨勬儏鍐碉紝涓昏鐩殑鏄負浜嗙粰涓涓姣斻傚湪姣旇緝涔嬩笅錛屾垜浠彲浠ユ洿鍔犳竻妤氬湴鐭ラ亾鍏跺唴閮ㄧ殑鍏蜂綋瀹炵幇銆?/p>
涓鑸戶鎵匡紙鏃犺櫄鍑芥暟瑕嗙洊錛?br>
涓嬮潰錛屽啀璁╂垜浠潵鐪嬬湅緇ф壙鏃剁殑铏氬嚱鏁拌〃鏄粈涔堟牱鐨勩傚亣璁炬湁濡備笅鎵紺虹殑涓涓戶鎵垮叧緋伙細
璇鋒敞鎰忥紝鍦ㄨ繖涓戶鎵垮叧緋諱腑錛屽瓙綾繪病鏈夐噸杞戒換浣曠埗綾葷殑鍑芥暟銆傞偅涔堬紝鍦ㄦ淳鐢熺被鐨勫疄渚嬩腑錛屽叾铏氬嚱鏁拌〃濡備笅鎵紺猴細
瀵逛簬瀹炰緥錛欴erive d; 鐨勮櫄鍑芥暟琛ㄥ涓嬶細
鎴戜滑鍙互鐪嬪埌涓嬮潰鍑犵偣錛?/p>
1錛夎櫄鍑芥暟鎸夌収鍏跺0鏄庨『搴忔斁浜庤〃涓?/p>
2錛夌埗綾葷殑铏氬嚱鏁板湪瀛愮被鐨勮櫄鍑芥暟鍓嶉潰銆?/p>
鎴戠浉淇¤仾鏄庣殑浣犱竴瀹氬彲浠ュ弬鑰冨墠闈㈢殑閭d釜紼嬪簭錛屾潵緙栧啓涓孌電▼搴忔潵楠岃瘉銆?/p>
涓鑸戶鎵匡紙鏈夎櫄鍑芥暟瑕嗙洊錛?br>
瑕嗙洊鐖剁被鐨勮櫄鍑芥暟鏄緢鏄劇劧鐨勪簨鎯咃紝涓嶇劧錛岃櫄鍑芥暟灝卞彉寰楁鏃犳剰涔夈備笅闈紝鎴戜滑鏉ョ湅涓涓嬶紝濡傛灉瀛愮被涓湁铏氬嚱鏁伴噸杞戒簡鐖剁被鐨勮櫄鍑芥暟錛屼細鏄竴涓粈涔堟牱瀛愶紵鍋囪錛屾垜浠湁涓嬮潰榪欐牱鐨勪竴涓戶鎵垮叧緋匯?/p>
涓轟簡璁╁ぇ瀹剁湅鍒拌緇ф壙榪囧悗鐨勬晥鏋滐紝鍦ㄨ繖涓被鐨勮璁′腑錛屾垜鍙鐩栦簡鐖剁被鐨勪竴涓嚱鏁幫細f()銆傞偅涔堬紝瀵逛簬媧劇敓綾葷殑瀹炰緥錛屽叾铏氬嚱鏁拌〃浼氭槸涓嬮潰鐨勪竴涓牱瀛愶細
鎴戜滑浠庤〃涓彲浠ョ湅鍒頒笅闈㈠嚑鐐癸紝
1錛夎鐩栫殑f()鍑芥暟琚斁鍒頒簡铏氳〃涓師鏉ョ埗綾昏櫄鍑芥暟鐨勪綅緗?/p>
2錛夋病鏈夎瑕嗙洊鐨勫嚱鏁頒緷鏃с?/p>
榪欐牱錛屾垜浠氨鍙互鐪嬪埌瀵逛簬涓嬮潰榪欐牱鐨勭▼搴忥紝
Base *b = new Derive();
b->f();
鐢眀鎵鎸囩殑鍐呭瓨涓殑铏氬嚱鏁拌〃鐨刦()鐨勪綅緗凡緇忚Derive::f()鍑芥暟鍦板潃鎵鍙栦唬錛屼簬鏄湪瀹為檯璋冪敤鍙戠敓鏃訛紝鏄疍erive::f()琚皟鐢ㄤ簡銆傝繖灝卞疄鐜頒簡澶氭併?/p>
澶氶噸緇ф壙錛堟棤铏氬嚱鏁拌鐩栵級
涓嬮潰錛屽啀璁╂垜浠潵鐪嬬湅澶氶噸緇ф壙涓殑鎯呭喌錛屽亣璁炬湁涓嬮潰榪欐牱涓涓被鐨勭戶鎵垮叧緋匯傛敞鎰忥細瀛愮被騫舵病鏈夎鐩栫埗綾葷殑鍑芥暟銆?/p>
瀵逛簬瀛愮被瀹炰緥涓殑铏氬嚱鏁拌〃錛屾槸涓嬮潰榪欎釜鏍峰瓙錛?/p>
鎴戜滑鍙互鐪嬪埌錛?/p>
1錛?nbsp; 姣忎釜鐖剁被閮芥湁鑷繁鐨勮櫄琛ㄣ?/p>
2錛?nbsp; 瀛愮被鐨勬垚鍛樺嚱鏁拌鏀懼埌浜嗙涓涓埗綾葷殑琛ㄤ腑銆傦紙鎵璋撶殑絎竴涓埗綾繪槸鎸夌収澹版槑欏哄簭鏉ュ垽鏂殑錛?/p>
榪欐牱鍋氬氨鏄負浜嗚В鍐充笉鍚岀殑鐖剁被綾誨瀷鐨勬寚閽堟寚鍚戝悓涓涓瓙綾誨疄渚嬶紝鑰岃兘澶熻皟鐢ㄥ埌瀹為檯鐨勫嚱鏁般?/p>
澶氶噸緇ф壙錛堟湁铏氬嚱鏁拌鐩栵級
涓嬮潰鎴戜滑鍐嶆潵鐪嬬湅錛屽鏋滃彂鐢熻櫄鍑芥暟瑕嗙洊鐨勬儏鍐點?/p>
涓嬪浘涓紝鎴戜滑鍦ㄥ瓙綾諱腑瑕嗙洊浜嗙埗綾葷殑f()鍑芥暟銆?/p>
涓嬮潰鏄浜庡瓙綾誨疄渚嬩腑鐨勮櫄鍑芥暟琛ㄧ殑鍥撅細
鎴戜滑鍙互鐪嬭錛屼笁涓埗綾昏櫄鍑芥暟琛ㄤ腑鐨刦()鐨勪綅緗鏇挎崲鎴愪簡瀛愮被鐨勫嚱鏁版寚閽堛傝繖鏍鳳紝鎴戜滑灝卞彲浠ヤ換涓闈欐佺被鍨嬬殑鐖剁被鏉ユ寚鍚戝瓙綾伙紝騫惰皟鐢ㄥ瓙綾葷殑f()浜嗐傚錛?/p>
Derive d;
Base1 *b1 = &d;
Base2 *b2 = &d;
Base3 *b3 = &d;
b1->f(); //Derive::f()
b2->f(); //Derive::f()
b3->f(); //Derive::f()
b1->g(); //Base1::g()
b2->g(); //Base2::g()
b3->g(); //Base3::g()
瀹夊叏鎬?br>
姣忔鍐機++鐨勬枃绔狅紝鎬誨厤涓嶄簡瑕佹壒鍒や竴涓婥++銆傝繖綃囨枃绔犱篃涓嶄緥澶栥傞氳繃涓婇潰鐨勮榪幫紝鐩鎬俊鎴戜滑瀵硅櫄鍑芥暟琛ㄦ湁涓涓瘮杈冪粏鑷寸殑浜嗚В浜嗐傛按鍙澆鑸燂紝浜﹀彲瑕嗚垷銆備笅闈紝璁╂垜浠潵鐪嬬湅鎴戜滑鍙互鐢ㄨ櫄鍑芥暟琛ㄦ潵騫茬偣浠涔堝潖浜嬪惂銆?/p>
涓銆侀氳繃鐖剁被鍨嬬殑鎸囬拡璁塊棶瀛愮被鑷繁鐨勮櫄鍑芥暟
鎴戜滑鐭ラ亾錛屽瓙綾繪病鏈夐噸杞界埗綾葷殑铏氬嚱鏁版槸涓浠舵鏃犳剰涔夌殑浜嬫儏銆傚洜涓哄鎬佷篃鏄鍩轟簬鍑芥暟閲嶈澆鐨勩傝櫧鐒跺湪涓婇潰鐨勫浘涓垜浠彲浠ョ湅鍒癇ase1鐨勮櫄琛ㄤ腑鏈塂erive鐨勮櫄鍑芥暟錛屼絾鎴戜滑鏍規湰涓嶅彲鑳戒嬌鐢ㄤ笅闈㈢殑璇彞鏉ヨ皟鐢ㄥ瓙綾葷殑鑷湁铏氬嚱鏁幫細
Base1 *b1 = new Derive();
b1->f1(); //緙栬瘧鍑洪敊
浠諱綍濡勫浘浣跨敤鐖剁被鎸囬拡鎯寵皟鐢ㄥ瓙綾諱腑鐨勬湭瑕嗙洊鐖剁被鐨勬垚鍛樺嚱鏁扮殑琛屼負閮戒細琚紪璇戝櫒瑙嗕負闈炴硶錛屾墍浠ワ紝榪欐牱鐨勭▼搴忔牴鏈棤娉曠紪璇戦氳繃銆備絾鍦ㄨ繍琛屾椂錛屾垜浠彲浠ラ氳繃鎸囬拡鐨勬柟寮忚闂櫄鍑芥暟琛ㄦ潵杈懼埌榪濆弽C++璇箟鐨勮涓恒傦紙鍏充簬榪欐柟闈㈢殑灝濊瘯錛岄氳繃闃呰鍚庨潰闄勫綍鐨勪唬鐮侊紝鐩鎬俊浣犲彲浠ュ仛鍒拌繖涓鐐癸級
浜屻佽闂畁on-public鐨勮櫄鍑芥暟
鍙﹀錛屽鏋滅埗綾葷殑铏氬嚱鏁版槸private鎴栨槸protected鐨勶紝浣嗚繖浜涢潪public鐨勮櫄鍑芥暟鍚屾牱浼氬瓨鍦ㄤ簬铏氬嚱鏁拌〃涓紝鎵浠ワ紝鎴戜滑鍚屾牱鍙互浣跨敤璁塊棶铏氬嚱鏁拌〃鐨勬柟寮忔潵璁塊棶榪欎簺non-public鐨勮櫄鍑芥暟錛岃繖鏄緢瀹規槗鍋氬埌鐨勩?/p>
濡傦細
class Base {
private:
virtual void f() { cout << "Base::f" << endl; }
};
class Derive : public Base{
};
typedef void(*Fun)(void);
void main() {
Derive d;
Fun pFun = (Fun)*((int*)*(int*)(&d)+0);
pFun();
}
緇撴潫璇?br>C++榪欓棬璇█鏄竴闂∕agic鐨勮璦錛屽浜庣▼搴忓憳鏉ヨ錛屾垜浠技涔庢案榪滄懜涓嶆竻妤氳繖闂ㄨ璦鑳岀潃鎴戜滑鍦ㄥ共浜嗕粈涔堛傞渶瑕佺啛鎮夎繖闂ㄨ璦錛屾垜浠氨蹇呴渶瑕佷簡瑙++閲岄潰鐨勯偅浜涗笢瑗匡紝闇瑕佸幓浜嗚ВC++涓偅浜涘嵄闄╃殑涓滆タ銆備笉鐒訛紝榪欐槸涓縐嶆惉璧風煶澶寸牳鑷繁鑴氱殑緙栫▼璇█銆?/p>
鍦ㄦ枃绔犳潫涔嬪墠榪樻槸浠嬬粛涓涓嬭嚜宸卞惂銆傛垜浠庝簨杞歡鐮斿彂鏈夊崄涓勾澶翠簡錛岀洰鍓嶆槸杞歡寮鍙戞妧鏈富綆★紝鎶鏈柟闈紝涓繪敾Unix/C/C++錛屾瘮杈冨枩嬈㈢綉緇滀笂鐨勬妧鏈紝姣斿鍒嗗竷寮忚綆楋紝緗戞牸璁$畻錛孭2P錛孉jax絳変竴鍒囧拰浜掕仈緗戠浉鍏崇殑涓滆タ銆傜鐞嗘柟闈㈡瘮杈冩搮闀夸簬鍥㈤槦寤鴻錛屾妧鏈秼鍔垮垎鏋愶紝欏圭洰綆$悊銆傛榪庡ぇ瀹跺拰鎴戜氦嫻侊紝鎴戠殑MSN鍜孍mail鏄細haoel@hotmail.com
闄勫綍涓錛歏C涓煡鐪嬭櫄鍑芥暟琛?br>
鎴戜滑鍙互鍦╒C鐨処DE鐜涓殑Debug鐘舵佷笅灞曞紑綾葷殑瀹炰緥灝卞彲浠ョ湅鍒拌櫄鍑芥暟琛ㄤ簡錛堝茍涓嶆槸寰堝畬鏁寸殑錛?/p>
闄勫綍 浜岋細渚嬬▼
涓嬮潰鏄竴涓叧浜庡閲嶇戶鎵跨殑铏氬嚱鏁拌〃璁塊棶鐨勪緥紼嬶細
#include <iostream>
using namespace std;
class Base1 {
public:
virtual void f() { cout << "Base1::f" << endl; }
virtual void g() { cout << "Base1::g" << endl; }
virtual void h() { cout << "Base1::h" << endl; }
};
class Base2 {
public:
virtual void f() { cout << "Base2::f" << endl; }
virtual void g() { cout << "Base2::g" << endl; }
virtual void h() { cout << "Base2::h" << endl; }
};
class Base3 {
public:
virtual void f() { cout << "Base3::f" << endl; }
virtual void g() { cout << "Base3::g" << endl; }
virtual void h() { cout << "Base3::h" << endl; }
};
class Derive : public Base1, public Base2, public Base3 {
public:
virtual void f() { cout << "Derive::f" << endl; }
virtual void g1() { cout << "Derive::g1" << endl; }
};
typedef void(*Fun)(void);
int main()
{
Fun pFun = NULL;
Derive d;
int** pVtab = (int**)&d;
//Base1's vtable
//pFun = (Fun)*((int*)*(int*)((int*)&d+0)+0);
pFun = (Fun)pVtab[0][0];
pFun();
//pFun = (Fun)*((int*)*(int*)((int*)&d+0)+1);
pFun = (Fun)pVtab[0][1];
pFun();
//pFun = (Fun)*((int*)*(int*)((int*)&d+0)+2);
pFun = (Fun)pVtab[0][2];
pFun();
//Derive's vtable
//pFun = (Fun)*((int*)*(int*)((int*)&d+0)+3);
pFun = (Fun)pVtab[0][3];
pFun();
//The tail of the vtable
pFun = (Fun)pVtab[0][4];
cout<<pFun<<endl;
//Base2's vtable
//pFun = (Fun)*((int*)*(int*)((int*)&d+1)+0);
pFun = (Fun)pVtab[1][0];
pFun();
//pFun = (Fun)*((int*)*(int*)((int*)&d+1)+1);
pFun = (Fun)pVtab[1][1];
pFun();
pFun = (Fun)pVtab[1][2];
pFun();
//The tail of the vtable
pFun = (Fun)pVtab[1][3];
cout<<pFun<<endl;
//Base3's vtable
//pFun = (Fun)*((int*)*(int*)((int*)&d+1)+0);
pFun = (Fun)pVtab[2][0];
pFun();
//pFun = (Fun)*((int*)*(int*)((int*)&d+1)+1);
pFun = (Fun)pVtab[2][1];
pFun();
pFun = (Fun)pVtab[2][2];
pFun();
//The tail of the vtable
pFun = (Fun)pVtab[2][3];
cout<<pFun<<endl;
return 0;
}
鏈枃鏉ヨ嚜CSDN鍗氬錛岃漿杞借鏍囨槑鍑哄錛?a >http://blog.csdn.net/haoel/archive/2007/12/18/1948051.aspx
闄堢殦
閲嶅緇ф壙
涓嬮潰鎴戜滑鍐嶆潵鐪嬬湅錛屽彂鐢熼噸澶嶇戶鎵跨殑鎯呭喌銆傛墍璋撻噸澶嶇戶鎵匡紝涔熷氨鏄煇涓熀綾昏闂存帴鍦伴噸澶嶇戶鎵夸簡澶氭銆?/p>
涓嬪浘鏄竴涓戶鎵垮浘錛屾垜浠噸杞戒簡鐖剁被鐨刦()鍑芥暟銆?/p>
鍏剁被緇ф壙鐨勬簮浠g爜濡備笅鎵紺恒傚叾涓紝姣忎釜綾婚兘鏈変袱涓彉閲忥紝涓涓槸鏁村艦錛?瀛楄妭錛夛紝涓涓槸瀛楃錛?瀛楄妭錛夛紝鑰屼笖榪樻湁鑷繁鐨勮櫄鍑芥暟錛岃嚜宸眔verwrite鐖剁被鐨勮櫄鍑芥暟銆傚瀛愮被D涓紝f()瑕嗙洊浜嗚秴綾葷殑鍑芥暟錛?f1() 鍜宖2() 瑕嗙洊浜嗗叾鐖剁被鐨勮櫄鍑芥暟錛孌f()涓鴻嚜宸辯殑铏氬嚱鏁般?/p>
class B
{
public:
int ib;
char cb;
public:
B():ib(0),cb('B') {}
virtual void f() { cout << "B::f()" << endl;}
virtual void Bf() { cout << "B::Bf()" << endl;}
};
class B1 : public B
{
public:
int ib1;
char cb1;
public:
B1():ib1(11),cb1('1') {}
virtual void f() { cout << "B1::f()" << endl;}
virtual void f1() { cout << "B1::f1()" << endl;}
virtual void Bf1() { cout << "B1::Bf1()" << endl;}
};
class B2: public B
{
public:
int ib2;
char cb2;
public:
B2():ib2(12),cb2('2') {}
virtual void f() { cout << "B2::f()" << endl;}
virtual void f2() { cout << "B2::f2()" << endl;}
virtual void Bf2() { cout << "B2::Bf2()" << endl;}
};
class D : public B1, public B2
{
public:
int id;
char cd;
public:
D():id(100),cd('D') {}
virtual void f() { cout << "D::f()" << endl;}
virtual void f1() { cout << "D::f1()" << endl;}
virtual void f2() { cout << "D::f2()" << endl;}
virtual void Df() { cout << "D::Df()" << endl;}
};
鎴戜滑鐢ㄦ潵瀛樺彇瀛愮被鍐呭瓨甯冨眬鐨勪唬鐮佸涓嬫墍紺猴細錛堝湪VC++ 2003鍜孏++ 3.4.4涓嬶級
typedef void(*Fun)(void);
int** pVtab = NULL;
Fun pFun = NULL;
D d;
pVtab = (int**)&d;
cout << "[0] D::B1::_vptr->" << endl;
pFun = (Fun)pVtab[0][0];
cout << " [0] "; pFun();
pFun = (Fun)pVtab[0][1];
cout << " [1] "; pFun();
pFun = (Fun)pVtab[0][2];
cout << " [2] "; pFun();
pFun = (Fun)pVtab[0][3];
cout << " [3] "; pFun();
pFun = (Fun)pVtab[0][4];
cout << " [4] "; pFun();
pFun = (Fun)pVtab[0][5];
cout << " [5] 0x" << pFun << endl;
cout << "[1] B::ib = " << (int)pVtab[1] << endl;
cout << "[2] B::cb = " << (char)pVtab[2] << endl;
cout << "[3] B1::ib1 = " << (int)pVtab[3] << endl;
cout << "[4] B1::cb1 = " << (char)pVtab[4] << endl;
cout << "[5] D::B2::_vptr->" << endl;
pFun = (Fun)pVtab[5][0];
cout << " [0] "; pFun();
pFun = (Fun)pVtab[5][1];
cout << " [1] "; pFun();
pFun = (Fun)pVtab[5][2];
cout << " [2] "; pFun();
pFun = (Fun)pVtab[5][3];
cout << " [3] "; pFun();
pFun = (Fun)pVtab[5][4];
cout << " [4] 0x" << pFun << endl;
cout << "[6] B::ib = " << (int)pVtab[6] << endl;
cout << "[7] B::cb = " << (char)pVtab[7] << endl;
cout << "[8] B2::ib2 = " << (int)pVtab[8] << endl;
cout << "[9] B2::cb2 = " << (char)pVtab[9] << endl;
cout << "[10] D::id = " << (int)pVtab[10] << endl;
cout << "[11] D::cd = " << (char)pVtab[11] << endl;
紼嬪簭榪愯緇撴灉濡備笅錛?/p>
GCC 3.4.4
VC++ 2003
[0] D::B1::_vptr->
[0] D::f()
[1] B::Bf()
[2] D::f1()
[3] B1::Bf1()
[4] D::f2()
[5] 0x1
[1] B::ib = 0
[2] B::cb = B
[3] B1::ib1 = 11
[4] B1::cb1 = 1
[5] D::B2::_vptr->
[0] D::f()
[1] B::Bf()
[2] D::f2()
[3] B2::Bf2()
[4] 0x0
[6] B::ib = 0
[7] B::cb = B
[8] B2::ib2 = 12
[9] B2::cb2 = 2
[10] D::id = 100
[11] D::cd = D
[0] D::B1::_vptr->
[0] D::f()
[1] B::Bf()
[2] D::f1()
[3] B1::Bf1()
[4] D::Df()
[5] 0x00000000
[1] B::ib = 0
[2] B::cb = B
[3] B1::ib1 = 11
[4] B1::cb1 = 1
[5] D::B2::_vptr->
[0] D::f()
[1] B::Bf()
[2] D::f2()
[3] B2::Bf2()
[4] 0x00000000
[6] B::ib = 0
[7] B::cb = B
[8] B2::ib2 = 12
[9] B2::cb2 = 2
[10] D::id = 100
[11] D::cd = D
涓嬮潰鏄浜庡瓙綾誨疄渚嬩腑鐨勮櫄鍑芥暟琛ㄧ殑鍥撅細
鎴戜滑鍙互鐪嬭錛屾渶欏剁鐨勭埗綾籅鍏舵垚鍛樺彉閲忓瓨鍦ㄤ簬B1鍜孊2涓紝騫惰D緇欑戶鎵夸笅鍘諱簡銆傝屽湪D涓紝鍏舵湁B1鍜孊2鐨勫疄渚嬶紝浜庢槸B鐨勬垚鍛樺湪D鐨勫疄渚嬩腑瀛樺湪涓や喚錛屼竴浠芥槸B1緇ф壙鑰屾潵鐨勶紝鍙︿竴浠芥槸B2緇ф壙鑰屾潵鐨勩傛墍浠ワ紝濡傛灉鎴戜滑浣跨敤浠ヤ笅璇彞錛屽垯浼氫駭鐢熶簩涔夋х紪璇戦敊璇細
D d;
d.ib = 0; //浜屼箟鎬ч敊璇?/p>
d.B1::ib = 1; //姝g‘
d.B2::ib = 2; //姝g‘
娉ㄦ剰錛屼笂闈緥紼嬩腑鐨勬渶鍚庝袱鏉¤鍙ュ瓨鍙栫殑鏄袱涓彉閲忋傝櫧鐒舵垜浠秷闄や簡浜屼箟鎬х殑緙栬瘧閿欒錛屼絾B綾誨湪D涓繕鏄湁涓や釜瀹炰緥錛岃繖縐嶇戶鎵塊犳垚浜嗘暟鎹殑閲嶅錛屾垜浠彨榪欑緇ф壙涓洪噸澶嶇戶鎵褲傞噸澶嶇殑鍩虹被鏁版嵁鎴愬憳鍙兘騫朵笉鏄垜浠兂瑕佺殑銆傛墍浠ワ紝C++寮曞叆浜嗚櫄鍩虹被鐨勬蹇點?/p>
閽葷煶鍨嬪閲嶈櫄鎷熺戶鎵?br>
铏氭嫙緇ф壙鐨勫嚭鐜板氨鏄負浜嗚В鍐抽噸澶嶇戶鎵夸腑澶氫釜闂存帴鐖剁被鐨勯棶棰樼殑銆傞捇鐭沖瀷鐨勭粨鏋勬槸鍏舵渶緇忓吀鐨勭粨鏋勩備篃鏄垜浠湪榪欓噷瑕佽璁虹殑緇撴瀯錛?/p>
涓婅堪鐨?#8220;閲嶅緇ф壙”鍙渶瑕佹妸B1鍜孊2緇ф壙B鐨勮娉曚腑鍔犱笂virtual 鍏抽敭錛屽氨鎴愪簡铏氭嫙緇ф壙錛屽叾緇ф壙鍥懼涓嬫墍紺猴細
涓婂浘鍜屽墠闈㈢殑“閲嶅緇ф壙”涓殑綾葷殑鍐呴儴鏁版嵁鍜屾帴鍙i兘鏄畬鍏ㄤ竴鏍風殑錛屽彧鏄垜浠噰鐢ㄤ簡铏氭嫙緇ф壙錛氬叾鐪佺暐鍚庣殑婧愮爜濡備笅鎵紺猴細
class B {……};
class B1 : virtual public B{……};
class B2: virtual public B{……};
class D : public B1, public B2{ …… };
鍦ㄦ煡鐪婦涔嬪墠錛屾垜浠厛鐪嬩竴鐪嬪崟涓铏氭嫙緇ф壙鐨勬儏鍐點備笅闈㈡槸涓孌靛湪VC++2003涓嬬殑嫻嬭瘯紼嬪簭錛氾紙鍥犱負VC++鍜孏CC鐨勫唴瀛樿屽眬涓婃湁涓浜涚粏鑺備笂鐨勪笉鍚岋紝鎵浠ヨ繖閲屽彧緇欏嚭VC++鐨勭▼搴忥紝GCC涓嬬殑紼嬪簭澶у鍙互鏍規嵁鎴戠粰鍑虹殑紼嬪簭鑷繁浠跨収鐫鍐欎竴涓幓璇曚竴璇曪級錛?/p>
int** pVtab = NULL;
Fun pFun = NULL;
B1 bb1;
pVtab = (int**)&bb1;
cout << "[0] B1::_vptr->" << endl;
pFun = (Fun)pVtab[0][0];
cout << " [0] ";
pFun(); //B1::f1();
cout << " [1] ";
pFun = (Fun)pVtab[0][1];
pFun(); //B1::bf1();
cout << " [2] ";
cout << pVtab[0][2] << endl;
cout << "[1] = 0x";
cout << (int*)*((int*)(&bb1)+1) <<endl; //B1::ib1
cout << "[2] B1::ib1 = ";
cout << (int)*((int*)(&bb1)+2) <<endl; //B1::ib1
cout << "[3] B1::cb1 = ";
cout << (char)*((int*)(&bb1)+3) << endl; //B1::cb1
cout << "[4] = 0x";
cout << (int*)*((int*)(&bb1)+4) << endl; //NULL
cout << "[5] B::_vptr->" << endl;
pFun = (Fun)pVtab[5][0];
cout << " [0] ";
pFun(); //B1::f();
pFun = (Fun)pVtab[5][1];
cout << " [1] ";
pFun(); //B::Bf();
cout << " [2] ";
cout << "0x" << (Fun)pVtab[5][2] << endl;
cout << "[6] B::ib = ";
cout << (int)*((int*)(&bb1)+6) <<endl; //B::ib
cout << "[7] B::cb = ";
鍏惰繍琛岀粨鏋滃涓嬶紙鎴戠粨鍑轟簡GCC鐨勫拰VC++2003鐨勫姣旓級錛?/p>
GCC 3.4.4
VC++ 2003
[0] B1::_vptr ->
[0] : B1::f()
[1] : B1::f1()
[2] : B1::Bf1()
[3] : 0
[1] B1::ib1 : 11
[2] B1::cb1 : 1
[3] B::_vptr ->
[0] : B1::f()
[1] : B::Bf()
[2] : 0
[4] B::ib : 0
[5] B::cb : B
[6] NULL : 0
[0] B1::_vptr->
[0] B1::f1()
[1] B1::Bf1()
[2] 0
[1] = 0x00454310 ç璇ュ湴鍧鍙栧煎悗鏄?4
[2] B1::ib1 = 11
[3] B1::cb1 = 1
[4] = 0x00000000
[5] B::_vptr->
[0] B1::f()
[1] B::Bf()
[2] 0x00000000
[6] B::ib = 0
[7] B::cb = B
榪欓噷錛屽ぇ瀹跺彲浠ヨ嚜宸卞姣斾竴涓嬨傚叧浜庣粏鑺備笂錛屾垜浼氬湪鍚庨潰涓騫跺啀璇淬?/p>
涓嬮潰鐨勬祴璇曠▼搴忔槸鐪嬪瓙綾籇鐨勫唴瀛樺竷灞錛屽悓鏍鋒槸VC++ 2003鐨勶紙鍥犱負VC++鍜孏CC鐨勫唴瀛樺竷灞涓婃湁涓浜涚粏鑺備笂鐨勪笉鍚岋紝鑰孷C++鐨勭浉瀵硅娓呮寰堝錛屾墍浠ヨ繖閲屽彧緇欏嚭VC++鐨勭▼搴忥紝GCC涓嬬殑紼嬪簭澶у鍙互鏍規嵁鎴戠粰鍑虹殑紼嬪簭鑷繁浠跨収鐫鍐欎竴涓幓璇曚竴璇曪級錛?/p>
D d;
pVtab = (int**)&d;
cout << "[0] D::B1::_vptr->" << endl;
pFun = (Fun)pVtab[0][0];
cout << " [0] "; pFun(); //D::f1();
pFun = (Fun)pVtab[0][1];
cout << " [1] "; pFun(); //B1::Bf1();
pFun = (Fun)pVtab[0][2];
cout << " [2] "; pFun(); //D::Df();
pFun = (Fun)pVtab[0][3];
cout << " [3] ";
cout << pFun << endl;
//cout << pVtab[4][2] << endl;
cout << "[1] = 0x";
cout << (int*)((&dd)+1) <<endl; //????
cout << "[2] B1::ib1 = ";
cout << *((int*)(&dd)+2) <<endl; //B1::ib1
cout << "[3] B1::cb1 = ";
cout << (char)*((int*)(&dd)+3) << endl; //B1::cb1
//---------------------
cout << "[4] D::B2::_vptr->" << endl;
pFun = (Fun)pVtab[4][0];
cout << " [0] "; pFun(); //D::f2();
pFun = (Fun)pVtab[4][1];
cout << " [1] "; pFun(); //B2::Bf2();
pFun = (Fun)pVtab[4][2];
cout << " [2] ";
cout << pFun << endl;
cout << "[5] = 0x";
cout << *((int*)(&dd)+5) << endl; // ???
cout << "[6] B2::ib2 = ";
cout << (int)*((int*)(&dd)+6) <<endl; //B2::ib2
cout << "[7] B2::cb2 = ";
cout << (char)*((int*)(&dd)+7) << endl; //B2::cb2
cout << "[8] D::id = ";
cout << *((int*)(&dd)+8) << endl; //D::id
cout << "[9] D::cd = ";
cout << (char)*((int*)(&dd)+9) << endl;//D::cd
cout << "[10] = 0x";
cout << (int*)*((int*)(&dd)+10) << endl;
//---------------------
cout << "[11] D::B::_vptr->" << endl;
pFun = (Fun)pVtab[11][0];
cout << " [0] "; pFun(); //D::f();
pFun = (Fun)pVtab[11][1];
cout << " [1] "; pFun(); //B::Bf();
pFun = (Fun)pVtab[11][2];
cout << " [2] ";
cout << pFun << endl;
cout << "[12] B::ib = ";
cout << *((int*)(&dd)+12) << endl; //B::ib
cout << "[13] B::cb = ";
cout << (char)*((int*)(&dd)+13) <<endl;//B::cb
涓嬮潰緇欏嚭榪愯鍚庣殑緇撴灉錛堝垎VC++鍜孏CC涓ら儴浠斤級
GCC 3.4.4
VC++ 2003
[0] B1::_vptr ->
[0] : D::f()
[1] : D::f1()
[2] : B1::Bf1()
[3] : D::f2()
[4] : D::Df()
[5] : 1
[1] B1::ib1 : 11
[2] B1::cb1 : 1
[3] B2::_vptr ->
[0] : D::f()
[1] : D::f2()
[2] : B2::Bf2()
[3] : 0
[4] B2::ib2 : 12
[5] B2::cb2 : 2
[6] D::id : 100
[7] D::cd : D
[8] B::_vptr ->
[0] : D::f()
[1] : B::Bf()
[2] : 0
[9] B::ib : 0
[10] B::cb : B
[11] NULL : 0
[0] D::B1::_vptr->
[0] D::f1()
[1] B1::Bf1()
[2] D::Df()
[3] 00000000
[1] = 0x0013FDC4 ç 璇ュ湴鍧鍙栧煎悗鏄?4
[2] B1::ib1 = 11
[3] B1::cb1 = 1
[4] D::B2::_vptr->
[0] D::f2()
[1] B2::Bf2()
[2] 00000000
[5] = 0x4539260 ç 璇ュ湴鍧鍙栧煎悗鏄?4
[6] B2::ib2 = 12
[7] B2::cb2 = 2
[8] D::id = 100
[9] D::cd = D
[10] = 0x00000000
[11] D::B::_vptr->
[0] D::f()
[1] B::Bf()
[2] 00000000
[12] B::ib = 0
[13] B::cb = B
鍏充簬铏氭嫙緇ф壙鐨勮繍琛岀粨鏋滄垜灝變笉鐢誨浘浜嗭紙鍓嶉潰鐨勪綔鍥懼凡緇忚鎴戜駭鐢熶簡寰堜弗閲嶇殑鍘屽︽劅錛屾墍浠ュ氨鍋蜂釜鎳掍簡錛屽ぇ瀹惰璋呬簡錛?/p>
鍦ㄤ笂闈㈢殑杈撳嚭緇撴灉涓紝鎴戠敤涓嶅悓鐨勯鑹插仛浜嗕竴浜涙爣鏄庛傛垜浠彲浠ョ湅鍒板涓嬬殑鍑犵偣錛?/p>
1錛夋棤璁烘槸GCC榪樻槸VC++錛岄櫎浜嗕竴浜涚粏鑺備笂鐨勪笉鍚岋紝鍏跺ぇ浣撲笂鐨勫璞″竷灞鏄竴鏍風殑銆備篃灝辨槸璇達紝鍏堟槸B1錛堥粍鑹詫級錛岀劧鍚庢槸B2錛堢豢鑹詫級錛屾帴鐫鏄疍錛堢伆鑹詫級錛岃孊榪欎釜瓚呯被錛堥潚钃濊壊錛夌殑瀹炰緥閮芥斁鍦ㄦ渶鍚庣殑浣嶇疆銆?/p>
2錛夊叧浜庤櫄鍑芥暟琛紝灝ゅ叾鏄涓涓櫄琛紝GCC鍜孷C++鏈夊緢閲嶅ぇ鐨勪笉涓鏍楓備絾浠旂粏鐪嬩笅鏉ワ紝榪樻槸VC++鐨勮櫄琛ㄦ瘮杈冩竻鏅板拰鏈夐昏緫鎬с?/p>
3錛塚C++鍜孏CC閮芥妸B榪欎釜瓚呯被鏀懼埌浜嗘渶鍚庯紝鑰孷C++鏈変竴涓狽ULL鍒嗛殧絎︽妸B鍜孊1鍜孊2鐨勫竷灞鍒嗗紑銆侴CC鍒欐病鏈夈?/p>
4錛塚C++涓殑鍐呭瓨甯冨眬鏈変袱涓湴鍧鎴戞湁浜涗笉鏄緢鏄庣櫧錛屽湪鍏朵腑鎴戠敤綰㈣壊鏍囧嚭浜嗐傚彇鍏跺唴瀹規槸-4銆傛帴閬撶悊鏉ヨ錛岃繖涓寚閽堝簲璇ユ槸鎸囧悜B綾誨疄渚嬬殑鍐呭瓨鍦板潃錛堣繖涓仛娉曞氨鏄負浜嗕繚璇侀噸澶嶇殑鐖剁被鍙湁涓涓疄渚嬬殑鎶鏈級銆備絾鍙栧煎悗鍗翠笉鏄傝繖鐐規垜鐩墠榪樺茍涓嶅お娓呮錛岃繕鍚戝ぇ瀹惰鏁欍?/p>
5錛塆CC鐨勫唴瀛樺竷灞涓湪B1鍜孊2涓垯娌℃湁鎸囧悜B鐨勬寚閽堛傝繖鐐瑰彲浠ョ悊瑙o紝緙栬瘧鍣ㄥ彲浠ラ氳繃璁$畻B1鍜孊2鐨剆ize鑰屽緱鍑築鐨勫亸縐婚噺銆?/p>
緇撴潫璇?br>C++榪欓棬璇█鏄竴闂ㄦ瘮杈冨鏉傜殑璇█錛屽浜庣▼搴忓憳鏉ヨ錛屾垜浠技涔庢案榪滄懜涓嶆竻妤氳繖闂ㄨ璦鑳岀潃鎴戜滑鍦ㄥ共浜嗕粈涔堛傞渶瑕佺啛鎮夎繖闂ㄨ璦錛屾垜浠氨蹇呴渶瑕佷簡瑙++閲岄潰鐨勯偅浜涗笢瑗匡紝闇瑕佹垜浠幓浜嗚В浠栧悗闈㈢殑鍐呭瓨瀵硅薄銆傝繖鏍鋒垜浠墠鑳界湡姝g殑浜嗚ВC++錛屼粠鑰岃兘澶熸洿濂界殑浣跨敤C++榪欓棬鏈闅劇殑緙栫▼璇█銆?/p>
鍦ㄦ枃绔犳潫涔嬪墠榪樻槸浠嬬粛涓涓嬭嚜宸卞惂銆傛垜浠庝簨杞歡鐮斿彂鏈夊崄涓勾澶翠簡錛岀洰鍓嶆槸杞歡寮鍙戞妧鏈富綆★紝鎶鏈柟闈紝涓繪敾Unix/C/C++錛屾瘮杈冨枩嬈㈢綉緇滀笂鐨勬妧鏈紝姣斿鍒嗗竷寮忚綆楋紝緗戞牸璁$畻錛孭2P錛孉jax絳変竴鍒囧拰浜掕仈緗戠浉鍏崇殑涓滆タ銆傜鐞嗘柟闈㈡瘮杈冩搮闀夸簬鍥㈤槦寤鴻錛屾妧鏈秼鍔垮垎鏋愶紝欏圭洰綆$悊銆傛榪庡ぇ瀹跺拰鎴戜氦嫻侊紝鎴戠殑MSN鍜孍mail鏄細haoel@hotmail.
鏈枃鏉ヨ嚜CSDN鍗氬錛岃漿杞借鏍囨槑鍑哄錛?a >http://blog.csdn.net/haoel/archive/2008/10/15/3081385.aspx
闄堢殦
鍓嶈█
07騫?2鏈堬紝鎴戝啓浜嗕竴綃囥奀++铏氬嚱鏁拌〃瑙f瀽銆嬬殑鏂囩珷錛屽紩璧蜂簡澶у鐨勫叴瓚c傛湁寰堝鏈嬪弸瀵規垜鐨勬枃绔犵暀浜嗚█錛屾湁榧撳姳鎴戠殑錛屾湁鎵硅瘎鎴戠殑錛岃繕鏈夊緢澶氶棶闂鐨勩傛垜鍦ㄨ繖閲屼竴騫跺澶у鐨勭暀璦琛ㄧず鎰熻阿銆傝繖涔熸槸鎴戜負浠涔堝啀鍐欎竴綃囩畫璦鐨勫師鍥犮傚洜涓猴紝鍦ㄤ笂涓綃囨枃绔犱腑錛屾垜鐢ㄤ簡鐨勭ず渚嬮兘鏄潪甯哥畝鍗曠殑錛屼富瑕佹槸涓轟簡璇存槑涓浜涙満鐞嗕笂鐨勯棶棰橈紝涔熸槸涓轟簡鍥句竴浜涜〃杈句笂鏂逛究鍜岀畝鍗曘備笉鎯籌紝榪欑瘒鏂囩珷鎴愪負浜嗘墦寮C++瀵硅薄妯″瀷鍐呭瓨甯冨眬鐨勪竴涓紩瀛愶紝寮曞彂浜嗗ぇ瀹跺C++瀵硅薄鐨勬洿娣卞眰嬈$殑璁ㄨ銆傚綋鐒訛紝鎴戜箣鍓嶇殑鏂囩珷榪樻湁寰堝鏂歸潰娌℃湁娑夊強錛屼粠鎴戜釜浜烘劅瑙変笅鏉ワ紝鍦ㄨ皥璁鴻櫄鍑芥暟琛ㄩ噷錛岃嚦灝戞湁浠ヤ笅榪欎簺鍐呭娌℃湁娑夊強錛?/p>
1錛夋湁鎴愬憳鍙橀噺鐨勬儏鍐點?/p>
2錛夋湁閲嶅緇ф壙鐨勬儏鍐點?/p>
3錛夋湁铏氭嫙緇ф壙鐨勬儏鍐點?/p>
4錛夋湁閽葷煶鍨嬭櫄鎷熺戶鎵跨殑鎯呭喌銆?/p>
榪欎簺閮芥槸鎴戞湰綃囨枃绔犻渶瑕佸悜澶у璇存槑鐨勪笢瑗褲傛墍浠ワ紝榪欑瘒鏂囩珷灝嗕細鏄奀++铏氬嚱鏁拌〃瑙f瀽銆嬬殑涓涓畫綃囷紝涔熸槸涓綃囬珮綰ц繘闃剁殑鏂囩珷銆傛垜甯屾湜澶у鍦ㄨ榪欑瘒鏂囩珷涔嬪墠瀵笴++鏈変竴瀹氱殑鍩虹鍜屼簡瑙o紝騫惰兘鍏堣鎴戠殑涓婁竴綃囨枃绔犮傚洜涓鴻繖綃囨枃绔犵殑娣卞害鍙兘浼氭瘮杈冩繁錛岃屼笖浼氭瘮杈冩潅涔憋紝鎴戝笇鏈涗綘鍦ㄨ鏈瘒鏂囩珷鏃朵笉浼氭湁澶ц剳鎬濈淮绱婁貢瀵艱嚧澶ц剳姝繪満鐨勬儏鍐點?-)
瀵硅薄鐨勫獎鍝嶅洜绱?br>
綆鑰岃█涔嬶紝鎴戜滑涓涓被鍙兘浼氭湁濡備笅鐨勫獎鍝嶅洜绱狅細
1錛夋垚鍛樺彉閲?/p>
2錛夎櫄鍑芥暟錛堜駭鐢熻櫄鍑芥暟琛級
3錛夊崟涓緇ф壙錛堝彧緇ф壙浜庝竴涓被錛?/p>
4錛夊閲嶇戶鎵匡紙緇ф壙澶氫釜綾伙級
5錛夐噸澶嶇戶鎵匡紙緇ф壙鐨勫涓埗綾諱腑鍏剁埗綾繪湁鐩稿悓鐨勮秴綾伙級
6錛夎櫄鎷熺戶鎵匡紙浣跨敤virtual鏂瑰紡緇ф壙錛屼負浜嗕繚璇佺戶鎵垮悗鐖剁被鐨勫唴瀛樺竷灞鍙細瀛樺湪涓浠斤級
涓婅堪鐨勪笢瑗塊氬父鏄疌++榪欓棬璇█鍦ㄨ涔夋柟闈㈠瀵硅薄鍐呴儴鐨勫獎鍝嶅洜绱狅紝褰撶劧錛岃繕浼氭湁緙栬瘧鍣ㄧ殑褰卞搷錛堟瘮濡備紭鍖栵級錛岃繕鏈夊瓧鑺傚榻愮殑褰卞搷銆傚湪榪欓噷鎴戜滑閮戒笉璁ㄨ錛屾垜浠彧璁ㄨC++璇█涓婄殑褰卞搷銆?/p>
鏈瘒鏂囩珷鐫閲嶈璁轟笅榪板嚑涓儏鍐典笅鐨凜++瀵硅薄鐨勫唴瀛樺竷灞鎯呭喌銆?/p>
1錛夊崟涓鐨勪竴鑸戶鎵匡紙甯︽垚鍛樺彉閲忋佽櫄鍑芥暟銆佽櫄鍑芥暟瑕嗙洊錛?/p>
2錛夊崟涓鐨勮櫄鎷熺戶鎵匡紙甯︽垚鍛樺彉閲忋佽櫄鍑芥暟銆佽櫄鍑芥暟瑕嗙洊錛?/p>
3錛夊閲嶇戶鎵匡紙甯︽垚鍛樺彉閲忋佽櫄鍑芥暟銆佽櫄鍑芥暟瑕嗙洊錛?/p>
4錛夐噸澶嶅閲嶇戶鎵匡紙甯︽垚鍛樺彉閲忋佽櫄鍑芥暟銆佽櫄鍑芥暟瑕嗙洊錛?/p>
5錛夐捇鐭沖瀷鐨勮櫄鎷熷閲嶇戶鎵匡紙甯︽垚鍛樺彉閲忋佽櫄鍑芥暟銆佽櫄鍑芥暟瑕嗙洊錛?/p>
鎴戜滑鐨勭洰鏍囧氨鏄紝璁╀簨鎯呰秺鏉ヨ秺澶嶆潅銆?/p>
鐭ヨ瘑澶嶄範
鎴戜滑綆鍗曞湴澶嶄範涓涓嬶紝鎴戜滑鍙互閫氳繃瀵硅薄鐨勫湴鍧鏉ュ彇寰楄櫄鍑芥暟琛ㄧ殑鍦板潃錛屽錛?/p>
typedef void(*Fun)(void);
Base b;
Fun pFun = NULL;
cout << "铏氬嚱鏁拌〃鍦板潃錛? << (int*)(&b) << endl;
cout << "铏氬嚱鏁拌〃 鈥?絎竴涓嚱鏁板湴鍧錛? << (int*)*(int*)(&b) << endl;
// Invoke the first virtual function
pFun = (Fun)*((int*)*(int*)(&b));
pFun();
鎴戜滑鍚屾牱鍙互鐢ㄨ繖縐嶆柟寮忔潵鍙栧緱鏁翠釜瀵硅薄瀹炰緥鐨勫唴瀛樺竷灞銆傚洜涓鴻繖浜涗笢瑗垮湪鍐呭瓨涓兘鏄繛緇垎甯冪殑錛屾垜浠彧闇瑕佷嬌鐢ㄩ傚綋鐨勫湴鍧鍋忕Щ閲忥紝鎴戜滑灝卞彲浠ヨ幏寰楁暣涓唴瀛樺璞$殑甯冨眬銆?/p>
鏈瘒鏂囩珷涓殑渚嬬▼鎴栧唴瀛樺竷灞涓昏浣跨敤濡備笅緙栬瘧鍣ㄥ拰緋葷粺錛?/p>
1錛塛indows XP 鍜?VC++ 2003
2錛塁ygwin 鍜?G++ 3.4.4
鍗曚竴鐨勪竴鑸戶鎵?br>
涓嬮潰錛屾垜浠亣璁炬湁濡備笅鎵紺虹殑涓涓戶鎵垮叧緋伙細
璇鋒敞鎰忥紝鍦ㄨ繖涓戶鎵垮叧緋諱腑錛岀埗綾伙紝瀛愮被錛屽瓩瀛愮被閮芥湁鑷繁鐨勪竴涓垚鍛樺彉閲忋傝屼簡綾昏鐩栦簡鐖剁被鐨刦()鏂規硶錛屽瓩瀛愮被瑕嗙洊浜嗗瓙綾葷殑g_child()鍙婂叾瓚呯被鐨刦()銆?/p>
鎴戜滑鐨勬簮紼嬪簭濡備笅鎵紺猴細
class Parent {
public:
int iparent;
Parent ():iparent (10) {}
virtual void f() { cout << " Parent::f()" << endl; }
virtual void g() { cout << " Parent::g()" << endl; }
virtual void h() { cout << " Parent::h()" << endl; }
};
class Child : public Parent {
public:
int ichild;
Child():ichild(100) {}
virtual void f() { cout << "Child::f()" << endl; }
virtual void g_child() { cout << "Child::g_child()" << endl; }
virtual void h_child() { cout << "Child::h_child()" << endl; }
};
class GrandChild : public Child{
public:
int igrandchild;
GrandChild():igrandchild(1000) {}
virtual void f() { cout << "GrandChild::f()" << endl; }
virtual void g_child() { cout << "GrandChild::g_child()" << endl; }
virtual void h_grandchild() { cout << "GrandChild::h_grandchild()" << endl; }
};
鎴戜滑浣跨敤浠ヤ笅紼嬪簭浣滀負嫻嬭瘯紼嬪簭錛氾紙涓嬮潰紼嬪簭涓紝鎴戜嬌鐢ㄤ簡涓涓猧nt** pVtab 鏉ヤ綔涓洪亶鍘嗗璞″唴瀛樺竷灞鐨勬寚閽堬紝榪欐牱錛屾垜灝卞彲浠ユ柟渚垮湴鍍忎嬌鐢ㄦ暟緇勪竴鏍鋒潵閬嶅巻鎵鏈夌殑鎴愬憳鍖呮嫭鍏惰櫄鍑芥暟琛ㄤ簡錛屽湪鍚庨潰鐨勭▼搴忎腑錛屾垜涔熸槸鐢ㄨ繖鏍風殑鏂規硶鐨勶紝璇蜂笉蹇呮劅鍒板鎬紝錛?/p>
typedef void(*Fun)(void);
GrandChild gc;
int** pVtab = (int**)&gc;
cout << "[0] GrandChild::_vptr->" << endl;
for (int i=0; (Fun)pVtab[0][i]!=NULL; i++){
pFun = (Fun)pVtab[0][i];
cout << " ["<<i<<"] ";
pFun();
}
cout << "[1] Parent.iparent = " << (int)pVtab[1] << endl;
cout << "[2] Child.ichild = " << (int)pVtab[2] << endl;
cout << "[3] GrandChild.igrandchild = " << (int)pVtab[3] << endl;
鍏惰繍琛岀粨鏋滃涓嬫墍紺猴細錛堝湪VC++ 2003鍜孏++ 3.4.4涓嬶級
[0] GrandChild::_vptr->
[0] GrandChild::f()
[1] Parent::g()
[2] Parent::h()
[3] GrandChild::g_child()
[4] Child::h1()
[5] GrandChild::h_grandchild()
[1] Parent.iparent = 10
[2] Child.ichild = 100
[3] GrandChild.igrandchild = 1000
浣跨敤鍥劇墖琛ㄧず濡備笅錛?/p>
鍙浠ヤ笅鍑犱釜鏂歸潰錛?/p>
1錛夎櫄鍑芥暟琛ㄥ湪鏈鍓嶉潰鐨勪綅緗?/p>
2錛夋垚鍛樺彉閲忔牴鎹叾緇ф壙鍜屽0鏄庨『搴忎緷嬈℃斁鍦ㄥ悗闈€?/p>
3錛夊湪鍗曚竴鐨勭戶鎵夸腑錛岃overwrite鐨勮櫄鍑芥暟鍦ㄨ櫄鍑芥暟琛ㄤ腑寰楀埌浜嗘洿鏂般?/p>
澶氶噸緇ф壙
涓嬮潰錛屽啀璁╂垜浠潵鐪嬬湅澶氶噸緇ф壙涓殑鎯呭喌錛屽亣璁炬湁涓嬮潰榪欐牱涓涓被鐨勭戶鎵垮叧緋匯傛敞鎰忥細瀛愮被鍙猳verwrite浜嗙埗綾葷殑f()鍑芥暟錛岃岃繕鏈変竴涓槸鑷繁鐨勫嚱鏁幫紙鎴戜滑榪欐牱鍋氱殑鐩殑鏄負浜嗙敤g1()浣滀負涓涓爣璁版潵鏍囨槑瀛愮被鐨勮櫄鍑芥暟琛級銆傝屼笖姣忎釜綾諱腑閮芥湁涓涓嚜宸辯殑鎴愬憳鍙橀噺錛?/p>
鎴戜滑鐨勭被緇ф壙鐨勬簮浠g爜濡備笅鎵紺猴細鐖剁被鐨勬垚鍛樺垵濮嬩負10錛?0錛?0錛屽瓙綾葷殑涓?00
class Base1 {
public:
int ibase1;
Base1():ibase1(10) {}
virtual void f() { cout << "Base1::f()" << endl; }
virtual void g() { cout << "Base1::g()" << endl; }
virtual void h() { cout << "Base1::h()" << endl; }
};
class Base2 {
public:
int ibase2;
Base2():ibase2(20) {}
virtual void f() { cout << "Base2::f()" << endl; }
virtual void g() { cout << "Base2::g()" << endl; }
virtual void h() { cout << "Base2::h()" << endl; }
};
class Base3 {
public:
int ibase3;
Base3():ibase3(30) {}
virtual void f() { cout << "Base3::f()" << endl; }
virtual void g() { cout << "Base3::g()" << endl; }
virtual void h() { cout << "Base3::h()" << endl; }
};
class Derive : public Base1, public Base2, public Base3 {
public:
int iderive;
Derive():iderive(100) {}
virtual void f() { cout << "Derive::f()" << endl; }
virtual void g1() { cout << "Derive::g1()" << endl; }
};
鎴戜滑閫氳繃涓嬮潰鐨勭▼搴忔潵鏌ョ湅瀛愮被瀹炰緥鐨勫唴瀛樺竷灞錛氫笅闈㈢▼搴忎腑錛屾敞鎰忔垜浣跨敤浜嗕竴涓猻鍙橀噺錛屽叾涓敤鍒頒簡sizof(Base)鏉ユ壘涓嬩竴涓被鐨勫亸縐婚噺銆傦紙鍥犱負鎴戝0鏄庣殑鏄痠nt鎴愬憳錛屾墍浠ユ槸4涓瓧鑺傦紝鎵浠ユ病鏈夊榻愰棶棰樸傚叧浜庡唴瀛樼殑瀵歸綈闂錛屽ぇ瀹跺彲浠ヨ嚜琛岃瘯楠岋紝鎴戝湪榪欓噷灝變笉澶氳浜嗭級
typedef void(*Fun)(void);
Derive d;
int** pVtab = (int**)&d;
cout << "[0] Base1::_vptr->" << endl;
pFun = (Fun)pVtab[0][0];
cout << " [0] ";
pFun();
pFun = (Fun)pVtab[0][1];
cout << " [1] ";pFun();
pFun = (Fun)pVtab[0][2];
cout << " [2] ";pFun();
pFun = (Fun)pVtab[0][3];
cout << " [3] "; pFun();
pFun = (Fun)pVtab[0][4];
cout << " [4] "; cout<<pFun<<endl;
cout << "[1] Base1.ibase1 = " << (int)pVtab[1] << endl;
int s = sizeof(Base1)/4;
cout << "[" << s << "] Base2::_vptr->"<<endl;
pFun = (Fun)pVtab[s][0];
cout << " [0] "; pFun();
Fun = (Fun)pVtab[s][1];
cout << " [1] "; pFun();
pFun = (Fun)pVtab[s][2];
cout << " [2] "; pFun();
pFun = (Fun)pVtab[s][3];
out << " [3] ";
cout<<pFun<<endl;
cout << "["<< s+1 <<"] Base2.ibase2 = " << (int)pVtab[s+1] << endl;
s = s + sizeof(Base2)/4;
cout << "[" << s << "] Base3::_vptr->"<<endl;
pFun = (Fun)pVtab[s][0];
cout << " [0] "; pFun();
pFun = (Fun)pVtab[s][1];
cout << " [1] "; pFun();
pFun = (Fun)pVtab[s][2];
cout << " [2] "; pFun();
pFun = (Fun)pVtab[s][3];
cout << " [3] ";
cout<<pFun<<endl;
s++;
cout << "["<< s <<"] Base3.ibase3 = " << (int)pVtab[s] << endl;
s++;
cout << "["<< s <<"] Derive.iderive = " << (int)pVtab[s] << endl;
鍏惰繍琛岀粨鏋滃涓嬫墍紺猴細錛堝湪VC++ 2003鍜孏++ 3.4.4涓嬶級
[0] Base1::_vptr->
[0] Derive::f()
[1] Base1::g()
[2] Base1::h()
[3] Driver::g1()
[4] 00000000 ç 娉ㄦ剰錛氬湪GCC涓嬶紝榪欓噷鏄?
[1] Base1.ibase1 = 10
[2] Base2::_vptr->
[0] Derive::f()
[1] Base2::g()
[2] Base2::h()
[3] 00000000 ç 娉ㄦ剰錛氬湪GCC涓嬶紝榪欓噷鏄?
[3] Base2.ibase2 = 20
[4] Base3::_vptr->
[0] Derive::f()
[1] Base3::g()
[2] Base3::h()
[3] 00000000
[5] Base3.ibase3 = 30
[6] Derive.iderive = 100
浣跨敤鍥劇墖琛ㄧず鏄笅闈㈣繖涓牱瀛愶細
鎴戜滑鍙互鐪嬪埌錛?/p>
1錛?nbsp; 姣忎釜鐖剁被閮芥湁鑷繁鐨勮櫄琛ㄣ?/p>
2錛?nbsp; 瀛愮被鐨勬垚鍛樺嚱鏁拌鏀懼埌浜嗙涓涓埗綾葷殑琛ㄤ腑銆?/p>
3錛?nbsp; 鍐呭瓨甯冨眬涓紝鍏剁埗綾誨竷灞渚濇鎸夊0鏄庨『搴忔帓鍒椼?/p>
4錛?nbsp; 姣忎釜鐖剁被鐨勮櫄琛ㄤ腑鐨刦()鍑芥暟閮借overwrite鎴愪簡瀛愮被鐨刦()銆傝繖鏍峰仛灝辨槸涓轟簡瑙e喅涓嶅悓鐨勭埗綾葷被鍨嬬殑鎸囬拡鎸囧悜鍚屼竴涓瓙綾誨疄渚嬶紝鑰岃兘澶熻皟鐢ㄥ埌瀹為檯鐨勫嚱鏁般?/p>
鏈枃鏉ヨ嚜CSDN鍗氬錛岃漿杞借鏍囨槑鍑哄錛?a >http://blog.csdn.net/haoel/archive/2008/10/15/3081328.aspx
璁板緱錛屾湁浣嶅井杞殑C++緲樻浜虹墿錛孒erb Sutter緇欒繖縐嶆妧宸хО涓篜impl ( Private Implemention ), 鐢ㄧ殑鎭板埌濂藉鏃訛紝鍙互鎻愰珮欏圭洰寮鍙戦熷害錛屽悓鏃舵ā鍧楃殑澶存枃浠墮棿鐨?include鍏崇郴寰椾互緙撹В錛屽彲浠ラ伩寮寰幆渚濊禆錛岃屼笖鍙互鑾峰緱涓涓壇濂界殑鐗╃悊璁捐銆?br>
鎬葷粨:
Pimpl鏂規硶鎰熻寰堜笉閿?
浣跨敤榪欎釜鏂規硶鐨勬椂鍊?涓瀹氳娉ㄦ剰鐨勬槸鍦ㄨ繖涓湴鏂圭殑鍙樺寲,榪欎釜鏄垜絎簩閬嶇湅鐨勬椂鍊欐墠娉ㄦ剰鍒扮殑.
class SoundSystem {
public:
// ...
private:
StreamFilter currentFilter;
EmitModeConfig modeConfig;
};
閲囩敤Pimpl鏂規硶鍚?鍙樹負
class SoundSystem {
public:
// ...
private:
StreamFilter* currentFilterPtr;
EmitModeConfig* modeConfigPtr;
};
鎵浠ュ湪.cpp鏂囦歡涓氨鏈変簡new鍜宒elete鐨勬搷浣?
瀵逛簬榪欑鏂規硶鏈変竴涓枒闂?瀵逛簬閭g瀛樺湪鍖呭惈浼楀綾葷殑鎯呭喌涓?榪欑鏂規硶鐨勯┚椹笉鏄竴鑸漢鑳藉鎺屾彙鐨勫惂.鎴栬榪欑鏂規硶灝變笉澶嬌鐢ㄤ簡,涓嶅絳夊緟涓浼?緙栬瘧.
// 鍒涘緩浜掓枼閲?br>HANDLE m_hMutex = CreateMutex(NULL, FALSE, "Sample07"); // 媯鏌ラ敊璇唬鐮?br>if (GetLastError() == ERROR_ALREADY_EXISTS) { 銆// 濡傛灉宸叉湁浜掓枼閲忓瓨鍦ㄥ垯閲婃斁鍙ユ焺騫跺浣嶄簰鏂ラ噺 銆CloseHandle(m_hMutex); 銆m_hMutex = NULL; 銆// 紼嬪簭閫鍑?br>銆return FALSE; } |
HANDLE CreateMutex( 銆LPSECURITY_ATTRIBUTES lpMutexAttributes, // 鎸囧悜瀹夊叏灞炴х殑鎸囬拡 銆BOOL bInitialOwner, // 鍒濆鍖栦簰鏂ュ璞$殑鎵鏈夎?br>銆LPCTSTR lpName // 鎸囧悜浜掓枼瀵硅薄鍚嶇殑鎸囬拡 ); |
浣跨敤vector鐨勬椂鍊欐渶濂藉姩鎬佸湴娣誨姞鍏冪礌銆傚畠涓嶅悓浜嶤鍜孞ava鎴栧叾浠栬璦鐨勬暟鎹被鍨嬶紝涓轟簡杈懼埌榪炵畫鎬э紝鏇存湁鏁堢殑鏂規硶鏄厛鍒濆鍖栦竴涓┖vector瀵硅薄錛岀劧鍚庡啀鍔ㄦ佹坊鍔犲厓绱狅紝鑰屼笉鏄鍏堝垎閰嶅唴瀛樸?/p>
22銆乿ector鍊煎垵濮嬪寲
鍐呯疆->0
鏈夐粯璁ゆ瀯閫?>璋冪敤榛樿鏋勯?/p>
鏃犻粯璁ゆ瀯閫狅紝鏈夊叾浠栨瀯閫?>紼嬪簭鍛樻墜鍔ㄦ彁渚涘垵濮嬪?/p>
鏃犻粯璁ゆ瀯閫狅紝涔熸棤鍏朵粬鏋勯?>鏍囧噯搴撲駭鐢熶竴涓甫鍒濆肩殑瀵硅薄
23銆佹暟緇勪笅鏍囩殑綾誨瀷
C++涓紝鏁扮粍涓嬫爣鐨勬紜被鍨嬫槸size_t鑰屼笉鏄痠nt錛宻ize_t鏄竴涓笌鏈哄櫒鐩稿叧鐨剈nsigned綾誨瀷銆?/p>
24銆佸湪澹版槑鎸囬拡鐨勬椂鍊欙紝鍙互鐢ㄧ┖鏍煎皢絎﹀彿*涓庡叾鍚庣殑鏍囪瘑絎﹀垎闅斿紑鏉ワ紝string *ps涓巗tring* ps閮芥槸鍙互鐨勶紝浣嗗悗鑰呭鏄撲駭鐢熻瑙o紝濡傦細
string* ps1,ps2; //ps1鏄寚閽堬紝鑰宲s2鏄竴涓猻tring瀵硅薄
涔熷氨鏄錛屼漢浠彲鑳借鎶妔tring鍜宻tring*褰撲綔涓や釜綾誨瀷錛屾垨鑰呰string*琚綋浣滀竴縐嶆柊綾誨瀷鏉ョ湅寰咃紝浣嗚繖鏄敊鐨?/u>錛?/p>
25銆佷竴涓湁鏁堢殑鎸囬拡蹇呯劧鏄互涓嬩笁縐嶇姸鎬佷箣涓錛?/p>
鍏朵腑int *pi=0;涓巌nt *pi;鏄笉鍚岀殑銆傚墠鑰呮槸鍒濆鍖栨寚閽堟寚鍚?鍦板潃鐨勫璞★紙鍗充負NULL錛夛紙pi initialized to address to no object錛夛紝鍚庤呭嵈鏄湭鍒濆鍖栫殑錛坥k, but dangerous, pi is uninitialized錛夈?/p>
緙栬瘧鍣ㄥ彲浠ユ嫻嬪嚭0鍊肩殑鎸囬拡錛岀▼搴忓彲鍒ゆ柇璇ユ寚閽堝茍鏈寚鍚戜竴涓璞★紝鑰屾湭鍒濆鍖栫殑鎸囬拡鐨勪嬌鐢ㄦ爣鍑嗗茍鏈畾涔夛紝瀵瑰ぇ澶氭暟緙栬瘧鍣ㄦ潵璇達紝濡傛灉浣跨敤鏈垵濮嬪寲鐨勬寚閽堜細灝嗘寚閽堜腑瀛樻斁鐨勪笉紜畾鍊艱涓哄湴鍧錛岀劧鍚庢搷綰佃鍐呭瓨鍦板潃涓瓨鏀劇殑浣嶅唴瀹癸紝浣跨敤鏈垵濮嬪寲鐨勬寚閽堢浉褰撲簬鎿嶇旱榪欎釜涓嶇‘瀹氱殑鍦板潃涓瓨鍌ㄧ殑鍩虹鏁版嵁錛屽洜姝ゅ鏈垵濮嬪寲鐨勬寚閽堣繘琛岃В寮曠敤鏃訛紝閫氬父浼氬鑷寸▼搴忓穿婧冦?/p>
26銆乿oid*鎸囬拡
void*鎸囬拡鍙敮鎸佸嚑縐嶆湁闄愮殑鎿嶄綔錛?/p>
涓嶅厑璁鎬嬌鐢╲oid*鎸囬拡鎿嶇旱瀹冩墍鎸囧悜鐨勫璞°?/p>
27銆佹寚閽堝拰寮曠敤鐨勬瘮杈冿紙P105錛?/p>
铏界劧浣跨敤寮曠敤錛坮eference錛夊拰鎸囬拡閮藉彲闂存帴璁塊棶鍙︿竴涓鹼紝浣嗗畠浠箣闂存湁涓や釜閲嶈鍖哄埆銆傜涓涓尯鍒湪浜庡紩鐢ㄦ繪槸鎸囧悜鏌愪釜瀵硅薄錛氬畾涔夊紩鐢ㄦ椂娌℃湁鍒濆鍖栨槸閿欒鐨勩傜浜屼釜閲嶈鍖哄埆鍒欐槸璧嬪艱涓虹殑宸紓錛氱粰寮曠敤璧嬪間慨鏀圭殑鏄寮曠敤鎵鍏寵仈鐨勫璞$殑鍊鹼紝鑰屽茍涓嶆槸浣垮紩鐢ㄤ笌鍙︿竴涓璞″叧鑱斻傚紩鐢ㄤ竴緇忓垵濮嬪寲錛屽氨濮嬬粓鎸囧悜鍚屼竴涓壒瀹氬璞★紙榪欏氨鏄負浠涔堝紩鐢ㄥ繀欏誨湪瀹氫箟鏃跺垵濮嬪寲鐨勫師鍥狅級銆?/p>
28銆佹寚閽堜笌typedef錛圥112錛?/p>
const鏀懼湪綾誨瀷鍓嶅拰鏀懼湪綾誨瀷鍚庨兘鍙互琛ㄧず鍚屾牱鐨勬剰鎬濓細
const string s1; string const s2;
s1鍜宻2鍧囪〃紺哄父閲忓瓧絎︿覆瀵硅薄銆?/p>
浣嗗洜姝ゅ氨瀵艱嚧浜嗕笅闈㈢殑鍙ュ瓙鍙兘浜х敓璇В錛?/p>
typedef string *pstring; const pstring cstr;
瀹規槗閿欐妸typedef褰撴垚鏂囨湰鎵╁睍鑰屼駭鐢熶笅闈㈢殑鐞嗚В錛?/p>
const string *cstr; //榪欏茍闈炰笂闈緥瀛愮殑姝g‘鎰忔濓紒錛堥敊璇級
搴旇浠庡0鏄庣殑鍙ュ瓙鐪嬶紝涔熷氨鏄鍙湅const pstring cstr;錛屽湪榪欓噷pstring鏄竴縐嶆寚閽堢被鍨嬶紝const淇グ鐨勬槸榪欎釜綾誨瀷錛屽洜姝ゆ紜殑鐞嗚В搴旇鏄細
string *const cstr;
鑰宑onst pstring cstr;鍏跺疄鍙互琛ㄧず涓簆string const cstr;錛岃繖鏍風殑鍐欐硶鍒欎笉瀹規槗浜х敓璇В銆備粠鍙沖悜宸﹂槄璇葷殑鎰忔濆氨鏄細cstr鏄痗onst pstring綾誨瀷錛屽嵆鎸囧悜string瀵硅薄鐨刢onst鎸囬拡銆?/p>
29銆佸垱寤哄姩鎬佹暟緇勶紙娉ㄦ剰鐐硅浠g爜娉ㄩ噴錛?/p>
const char *cp1 = "some value"; char *cp2 = "other value"; int *piArray1 = new int[10]; //鍐呯疆綾誨瀷娌℃湁鍒濆鍖? int *piArray2 = new int[10](); //鍐呯疆綾誨瀷闇瑕佸姞絀哄渾鎷彿錛屽鏁扮粍鍏冪礌榪涜鍒濆鍖? std::string *psArray1 = new std::string[10]; //榛樿鏋勯犲嚱鏁板垵濮嬪寲 std::cout<<"----------"<<std::endl <<"*cp1\t\t:"<<*cp1<<std::endl <<"*cp2\t\t:"<<*cp2<<std::endl <<"*piArray1\t:"<<*piArray1<<std::endl <<"*piArray2\t:"<<*piArray2<<std::endl <<"*psArray1\t:"<<*psArray1<<std::endl <<"----------"<<std::endl;
浣嗘槸涓嬮潰鐨勭粨鏋滃嵈涓庢蹇典笂鐨勪笉鍚岋細
////Visual Studio & MS VC++
//----------
//*cp1 :s
//*cp2 :o
//*piArray1 :-842150451
//*piArray2 :0
//*psArray1 :
//----------
////Eclipse&G++
//----------
//*cp1 :s
//*cp2 :o
//*piArray1 :4064608
//*piArray2 :4064560
//*psArray1 :
//----------
鐪嬫潵涓嶅悓鐨勭紪璇戝櫒瀵規鐨勫畾涔夎繕鏄湁鎵涓嶅悓錛屾敞鎰忕湅*piArray2鐨勫鹼紝鎸夌収璇存槑搴旇鏄垵濮嬪寲涓?錛屼絾榪欓噷鍗翠粛鐒惰〃鐜板嚭涓?piArray1涓鏍風殑鍊鹼紝璇存槑騫舵病鏈夊彂鐢熷垵濮嬪寲銆?/p>
瀵逛簬鍔ㄦ佸垎閰嶇殑鏁扮粍錛屽叾鍏冪礌鍙兘鍒濆鍖栦負鍏冪礌綾誨瀷鐨勯粯璁ゅ鹼紝鑰屼笉鑳藉儚鏁扮粍鍙橀噺涓鏍鳳紝鐢ㄥ垵濮嬪寲鍒楄〃涓烘暟緇勫厓绱犳彁渚涘悇涓嶇浉鍚岀殑鍒濆箋?/p>
30銆乧onst瀵硅薄鐨勫姩鎬佹暟緇?/p>
//P118 //error:uninitialized const array const int *pciArray1 = new const int[10]; //ok:value-initialized const array const int *pciArray2 = new const int[10](); std::cout<<*pciArray1<<std::endl; std::cout<<*pciArray2<<std::endl;
涓婇潰鐨勭ず渚嬬殑娉ㄩ噴鏉ヨ嚜涔︿腑錛屼絾鍦╒C++緙栬瘧鍣ㄥ拰G++緙栬瘧鍣ㄤ笅鍗翠笉鍚岋紝鍏蜂綋琛ㄧ幇涓猴細
鐪嬫潵涓や釜緙栬瘧鍣ㄥ榪欎竴闂鐨勭湅娉曚笉澶竴鑷淬?/p>
闂錛氬綋榪愯鏃墮敊璇駭鐢熸椂錛屾垜鎬庢牱鎵嶈兘寰楀埌鍖呭惈C++鏂囦歡鍚嶅拰琛屽彿鐨勫瓧絎︿覆淇℃伅錛?br>鍥炵瓟錛氬湪C++涓殑__FILE__棰勭紪璇戞寚紺哄櫒鍖呭惈浜嗚緙栬瘧鐨勬枃浠跺悕錛岃宊_LINE__鍒欏寘鍚簡婧愪唬鐮佺殑琛屽彿銆俖_FILE__鍜宊_LINE__鐨勫墠鍚庨兘鍖呭惈浜?span style="COLOR: red">涓や釜涓嬪垝綰匡紝璁╂垜浠粩緇嗙湅鐪媉_FILE__鎵鍖呭惈鐨勬瘡涓瓧絎︼細
_ _ F I L E _ _
涓嬮潰灞曠ず浜嗗湪鎺у埗鍙扮▼搴忎腑濡傛灉鏄劇ず鏂囦歡鍚嶅拰浠g爜琛屽彿銆?br>
#include <stdio.h>
int main(int , char**)
{
printf("This fake error is in %s on line %d\n", __FILE__, __LINE__);
return 0;
}
杈撳嚭緇撴灉錛?br>
This fake error is in c:\temp\test.cpp on line 5
鎴戞兂閫氳繃涓涓氱敤鍑芥暟error()鏉ユ姤鍛婇敊璇紝浠ヤ嬌褰撴煇涓敊璇彂鐢熸椂鎴戣兘璁劇疆鏂偣浠ュ強闅旂閿欒澶勭悊錛堜緥濡傦紝鍦ㄥ睆騫曚笂鎵撳嵃閿欒淇℃伅鎴栬呭啓鍏ユ棩蹇楋級銆傚洜姝わ紝鍑芥暟鐨勫師鍨嬪簲璇ユ槸榪欐牱鐨勫惂錛?br>
榪欓噷鏈変笁涓棶棰橀渶瑕佽В鍐籌細
__FILE__鍜宊_LINE__搴旇琚嚜鍔ㄥ鐞嗭紝鑰岄潪姣忔浣滀負鍙傛暟浼犻掔粰error錛岃繖鏍蜂細璁〆rror鐨勪嬌鐢ㄨ呮劅瑙夋洿鐖戒簺錛屽畠鐨勫艦寮忓彲鑳芥槸涓嬮潰榪欐牱錛?br>
鎴戝笇鏈涗笂闈㈢殑瀹廇T灞曞紑涓猴細"c:\temp\test.cpp:5"銆傝屾柊鐨別rror鍑芥暟鍒欏彉鎴愶細
鍥犱負Borland C++ Builder緙栬瘧鍣ㄨ兘澶熻嚜鍔ㄥ悎騫剁浉閭葷殑瀛楃涓詫紝鍥犳鎴戞妸AT鍐欐垚涓嬮潰榪欐牱錛?br>
鐒惰屽畠鍗寸艦宸ヤ簡錛屽洜涓篲_LINE__琚墿灞曟垚浜嗘暣鏁拌岄潪瀛楃涓詫紝鎵浠ュ畯灞曞紑鍚庡彉鎴愶細
"c:\temp\test.cpp" ":" 5
榪欐槸涓涓棤鏁堢殑瀛楃涓詫紝鍥犱負鏈熬鏈変竴涓湭琚弻寮曞彿鍖呭惈鐨勬暣鏁般?
鎬庝箞鍔烇紵鍒潃鎬ワ紝涓涓壒孌婄殑棰勭紪璇戞寚紺哄櫒“#”鑳藉甯垜浠皢涓涓彉閲忚漿鎹㈡垚瀛楃涓層傛墍浠ラ噸鏂板畾涔夊畯錛?
#define AT __FILE__ ":" #__LINE__
鍢垮樋錛岃繖鏍鋒昏浜嗗惂銆傚埆楂樺叴寰楀お鏃╋紝榪欐牱涔熸槸涓嶈鐨勩傚洜涓虹紪璇戝櫒浼氭姳鎬?鏄釜鏃犳晥瀛楃銆傚叾瀹烇紝闂鏄?棰勭紪璇戞寚紺哄櫒鍙湁榪欐牱浣跨敤鎵嶄細
琚紜瘑鍒細
#define symbol(X) #X
瑙e喅鏂規硶鏄啀鐢ㄤ竴涓畯鏉ュ寘瑁匰TRINGIFY()錛?br>
http://www.shnenglu.com/iuranus/archive/2008/12/25/70315.html
鍏蜂綋褰掔撼濡備笅:
reinterpret_cast
璇ュ嚱鏁板皢涓涓被鍨嬬殑鎸囬拡杞崲涓哄彟涓涓被鍨嬬殑鎸囬拡.
榪欑杞崲涓嶇敤淇敼鎸囬拡鍙橀噺鍊煎瓨鏀炬牸寮?涓嶆敼鍙樻寚閽堝彉閲忓?,鍙渶鍦ㄧ紪璇戞椂閲嶆柊瑙i噴鎸囬拡鐨勭被鍨嬪氨鍙仛鍒?
reinterpret_cast 鍙互灝嗘寚閽堝艱漿鎹負涓涓暣鍨嬫暟,浣嗕笉鑳界敤浜庨潪鎸囬拡綾誨瀷鐨勮漿鎹?
渚?
//鍩烘湰綾誨瀷鎸囬拡鐨勭被鍨嬭漿鎹?br>double d=9.2;
double* pd = &d;
int *pi = reinterpret_cast<int*>(pd); //鐩稿綋浜巌nt *pi = (int*)pd;
//涓嶇浉鍏崇殑綾葷殑鎸囬拡鐨勭被鍨嬭漿鎹?br>class A{};
class B{};
A* pa = new A;
B* pb = reinterpret_cast<B*>(pa); //鐩稿綋浜嶣* pb = (B*)pa;
//鎸囬拡杞崲涓烘暣鏁?br>long l = reinterpret_cast<long>(pi); //鐩稿綋浜巐ong l = (long)pi;
const_cast
璇ュ嚱鏁扮敤浜庡幓闄ゆ寚閽堝彉閲忕殑甯擱噺灞炴э紝灝嗗畠杞崲涓轟竴涓搴旀寚閽堢被鍨嬬殑鏅氬彉閲忋傚弽榪囨潵錛屼篃鍙互灝嗕竴涓潪甯擱噺鐨勬寚閽堝彉閲忚漿鎹負涓涓父鎸囬拡鍙橀噺銆?br>榪欑杞崲鏄湪緙栬瘧鏈熼棿鍋氬嚭鐨勭被鍨嬫洿鏀廣?br>渚嬶細
const int* pci = 0;
int* pk = const_cast<int*>(pci); //鐩稿綋浜巌nt* pk = (int*)pci;
const A* pca = new A;
A* pa = const_cast<A*>(pca); //鐩稿綋浜嶢* pa = (A*)pca;
鍑轟簬瀹夊叏鎬ц冭檻錛宑onst_cast鏃犳硶灝嗛潪鎸囬拡鐨勫父閲忚漿鎹負鏅氬彉閲忋?/p>
static_cast
璇ュ嚱鏁頒富瑕佺敤浜庡熀鏈被鍨嬩箣闂村拰鍏鋒湁緇ф壙鍏崇郴鐨勭被鍨嬩箣闂寸殑杞崲銆?br>榪欑杞崲涓鑸細鏇存敼鍙橀噺鐨勫唴閮ㄨ〃紺烘柟寮忥紝鍥犳錛宻tatic_cast搴旂敤浜庢寚閽堢被鍨嬭漿鎹㈡病鏈夊お澶ф剰涔夈?br>渚嬶細
//鍩烘湰綾誨瀷杞崲
int i=0;
double d = static_cast<double>(i); //鐩稿綋浜?double d = (double)i;
//杞崲緇ф壙綾葷殑瀵硅薄涓哄熀綾誨璞?br>class Base{};
class Derived : public Base{};
Derived d;
Base b = static_cast<Base>(d); //鐩稿綋浜?Base b = (Base)d;
dynamic_cast
瀹冧笌static_cast鐩稿錛屾槸鍔ㄦ佽漿鎹€?br>榪欑杞崲鏄湪榪愯鏃惰繘琛岃漿鎹㈠垎鏋愮殑錛屽茍闈炲湪緙栬瘧鏃惰繘琛岋紝鏄庢樉鍖哄埆浜庝笂闈笁涓被鍨嬭漿鎹㈡搷浣溿?br>璇ュ嚱鏁板彧鑳藉湪緇ф壙綾誨璞$殑鎸囬拡涔嬮棿鎴栧紩鐢ㄤ箣闂磋繘琛岀被鍨嬭漿鎹€傝繘琛岃漿鎹㈡椂錛屼細鏍規嵁褰撳墠榪愯鏃剁被鍨嬩俊鎭紝鍒ゆ柇綾誨瀷瀵硅薄涔嬮棿鐨勮漿鎹㈡槸鍚﹀悎娉曘俤ynamic_cast鐨勬寚閽堣漿鎹㈠け璐ワ紝鍙氳繃鏄惁涓簄ull媯嫻嬶紝寮曠敤杞崲澶辮觸鍒欐姏鍑轟竴涓猙ad_cast寮傚父銆?br>渚嬶細
class Base{};
class Derived : public Base{};
//媧劇敓綾繪寚閽堣漿鎹負鍩虹被鎸囬拡
Derived *pd = new Derived;
Base *pb = dynamic_cast<Base*>(pd);
if (!pb)
cout << "綾誨瀷杞崲澶辮觸" << endl;
//娌℃湁緇ф壙鍏崇郴錛屼絾琚漿鎹㈢被鏈夎櫄鍑芥暟
class A(virtual ~A();) //鏈夎櫄鍑芥暟
class B{}:
A* pa = new A;
B* pb = dynamic_cast<B*>(pa);
濡傛灉瀵規棤緇ф壙鍏崇郴鎴栬呮病鏈夎櫄鍑芥暟鐨勫璞℃寚閽堣繘琛岃漿鎹€佸熀鏈被鍨嬫寚閽堣漿鎹互鍙婂熀綾繪寚閽堣漿鎹負媧劇敓綾繪寚閽堬紝閮戒笉鑳介氳繃緙栬瘧銆?/p>
鏍囩錛?鏃犳爣絳?/p>
1銆佸垱寤哄拰緇堟綰跨▼
銆銆鍦∕FC紼嬪簭涓垱寤轟竴涓嚎紼嬶紝瀹滆皟鐢ˋfxBeginThread鍑芥暟銆傝鍑芥暟鍥犲弬鏁頒笉鍚岃屽叿鏈変袱縐嶉噸杞界増鏈紝鍒嗗埆瀵瑰簲宸ヤ綔鑰呯嚎紼嬪拰鐢ㄦ埛鎺ュ彛錛圲I錛夌嚎紼嬨?br>
銆銆宸ヤ綔鑰呯嚎紼?br>
CWinThread *AfxBeginThread( 銆AFX_THREADPROC pfnThreadProc, //鎺у埗鍑芥暟 銆LPVOID pParam, //浼犻掔粰鎺у埗鍑芥暟鐨勫弬鏁?br>銆int nPriority = THREAD_PRIORITY_NORMAL, //綰跨▼鐨勪紭鍏堢駭 銆UINT nStackSize = 0, //綰跨▼鐨勫爢鏍堝ぇ灝?br>銆DWORD dwCreateFlags = 0, //綰跨▼鐨勫垱寤烘爣蹇?br>銆LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL //綰跨▼鐨?a class=bluekey target=_blank>瀹夊叏灞炴?br>); |
//綰跨▼鎺у埗鍑芥暟 UINT MfcThreadProc(LPVOID lpParam) { 銆CExampleClass *lpObject = (CExampleClass*)lpParam; 銆if (lpObject == NULL || !lpObject->IsKindof(RUNTIME_CLASS(CExampleClass))) 銆銆return - 1; //杈撳叆鍙傛暟闈炴硶 銆//綰跨▼鎴愬姛鍚姩 銆while (1) 銆 銆return 0; } //鍦∕FC紼嬪簭涓惎鍔ㄧ嚎紼?br>AfxBeginThread(MfcThreadProc, lpObject); |
class CWinThread : public CCmdTarget { 銆DECLARE_DYNAMIC(CWinThread) 銆public: 銆銆// Constructors 銆銆CWinThread(); 銆銆BOOL CreateThread(DWORD dwCreateFlags = 0, UINT nStackSize = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL); 銆銆// Attributes 銆銆CWnd* m_pMainWnd; // main window (usually same AfxGetApp()->m_pMainWnd) 銆銆CWnd* m_pActiveWnd; // active main window (may not be m_pMainWnd) 銆銆BOOL m_bAutoDelete; // enables 'delete this' after thread termination 銆銆// only valid while running 銆銆HANDLE m_hThread; // this thread's HANDLE 銆銆operator HANDLE() const; 銆銆DWORD m_nThreadID; // this thread's ID 銆銆int GetThreadPriority(); 銆銆BOOL SetThreadPriority(int nPriority); 銆銆// Operations 銆銆DWORD SuspendThread(); 銆銆DWORD ResumeThread(); 銆銆BOOL PostThreadMessage(UINT message, WPARAM wParam, LPARAM lParam); 銆銆// Overridables 銆銆//鎵ц綰跨▼瀹炰緥鍒濆鍖栵紝蹇呴』閲嶅啓 銆銆virtual BOOL InitInstance(); 銆銆// running and idle processing 銆銆//鎺у埗綰跨▼鐨勫嚱鏁幫紝鍖呭惈娑堟伅娉碉紝涓鑸笉閲嶅啓 銆銆virtual int Run(); 銆銆//娑堟伅璋冨害鍒癟ranslateMessage鍜孌ispatchMessage涔嬪墠瀵瑰叾榪涜絳涢夛紝 銆銆//閫氬父涓嶉噸鍐?br>銆銆virtual BOOL PreTranslateMessage(MSG* pMsg); 銆銆virtual BOOL PumpMessage(); // low level message pump 銆銆//鎵ц綰跨▼鐗瑰畾鐨勯棽緗椂闂村鐞嗭紝閫氬父涓嶉噸鍐?br>銆銆virtual BOOL OnIdle(LONG lCount); // return TRUE if more idle processing 銆銆virtual BOOL IsIdleMessage(MSG* pMsg); // checks for special messages 銆銆//綰跨▼緇堟鏃舵墽琛屾竻闄わ紝閫氬父闇瑕侀噸鍐?br>銆銆virtual int ExitInstance(); // default will 'delete this' 銆銆//鎴幏鐢辯嚎紼嬬殑娑堟伅鍜屽懡浠ゅ鐞嗙▼搴忓紩鍙戠殑鏈鐞嗗紓甯革紝閫氬父涓嶉噸鍐?br>銆銆virtual LRESULT ProcessWndProcException(CException* e, const MSG* pMsg); 銆銆// Advanced: handling messages sent to message filter hook 銆銆virtual BOOL ProcessMessageFilter(int code, LPMSG lpMsg); 銆銆// Advanced: virtual access to m_pMainWnd 銆銆virtual CWnd* GetMainWnd(); 銆銆// Implementation 銆public: 銆銆virtual ~CWinThread(); 銆銆#ifdef _DEBUG 銆銆銆virtual void AssertValid() const; 銆銆銆virtual void Dump(CDumpContext& dc) const; 銆銆銆int m_nDisablePumpCount; // Diagnostic trap to detect illegal re-entrancy 銆銆#endif 銆銆void CommonConstruct(); 銆銆virtual void Delete(); 銆銆// 'delete this' only if m_bAutoDelete == TRUE 銆銆// message pump for Run 銆銆MSG m_msgCur; // current message 銆public: 銆銆// constructor used by implementation of AfxBeginThread 銆銆CWinThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam); 銆銆// valid after construction 銆銆LPVOID m_pThreadParams; // generic parameters passed to starting function 銆銆AFX_THREADPROC m_pfnThreadProc; 銆銆// set after OLE is initialized 銆銆void (AFXAPI* m_lpfnOleTermOrFreeLib)(BOOL, BOOL); 銆銆COleMessageFilter* m_pMessageFilter; 銆protected: 銆銆CPoint m_ptCursorLast; // last mouse position 銆銆UINT m_nMsgLast; // last mouse message 銆銆BOOL DispatchThreadMessageEx(MSG* msg); // helper 銆銆void DispatchThreadMessage(MSG* msg); // obsolete }; |
CWinThread *AfxBeginThread( 銆//浠嶤WinThread媧劇敓鐨勭被鐨?RUNTIME_CLASS 銆CRuntimeClass *pThreadClass, 銆int nPriority = THREAD_PRIORITY_NORMAL, 銆UINT nStackSize = 0, 銆DWORD dwCreateFlags = 0, 銆LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL ); |
![]() |
///////////////////////////////////////////////////////////////////////////// // CMyUIThread thread class CMyUIThread : public CWinThread { 銆DECLARE_DYNCREATE(CMyUIThread) 銆protected: 銆銆CMyUIThread(); // protected constructor used by dynamic creation 銆銆// Attributes 銆public: 銆銆// Operations 銆public: 銆銆// Overrides 銆銆// ClassWizard generated virtual function overrides 銆銆//{{AFX_VIRTUAL(CMyUIThread) 銆銆public: 銆銆銆virtual BOOL InitInstance(); 銆銆銆virtual int ExitInstance(); 銆銆//}}AFX_VIRTUAL 銆銆// Implementation 銆protected: 銆銆virtual ~CMyUIThread(); 銆銆// Generated message map functions 銆銆//{{AFX_MSG(CMyUIThread) 銆銆銆// NOTE - the ClassWizard will add and remove member functions here. 銆銆//}}AFX_MSG 銆DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////// // CMyUIThread IMPLEMENT_DYNCREATE(CMyUIThread, CWinThread) CMyUIThread::CMyUIThread() {} CMyUIThread::~CMyUIThread() {} BOOL CMyUIThread::InitInstance() { 銆// TODO: perform and per-thread initialization here 銆return TRUE; } int CMyUIThread::ExitInstance() { 銆// TODO: perform any per-thread cleanup here 銆return CWinThread::ExitInstance(); } BEGIN_MESSAGE_MAP(CMyUIThread, CWinThread) //{{AFX_MSG_MAP(CMyUIThread) // NOTE - the ClassWizard will add and remove mapping macros here. //}}AFX_MSG_MAP END_MESSAGE_MAP() |
CMyUIThread *pThread; pThread = (CMyUIThread*) AfxBeginThread( RUNTIME_CLASS(CMyUIThread) ); |
void AfxEndThread( 銆UINT nExitCode //the exit code of the thread ); |
銆銆瀵逛簬UI綰跨▼鑰岃█錛屽鏋滄秷鎭槦鍒椾腑鏀懼叆浜哤M_QUIT娑堟伅錛屽皢緇撴潫綰跨▼銆?br>
銆銆鍏充簬UI綰跨▼鍜屽伐浣滆呯嚎紼嬬殑鍒嗛厤錛屾渶濂界殑鍋氭硶鏄細灝嗘墍鏈変笌UI鐩稿叧鐨勬搷浣滄斁鍏ヤ富綰跨▼錛屽叾瀹冪殑綰補鐨勮繍綆楀伐浣滀氦緇欑嫭绔嬬殑鏁頒釜宸ヤ綔鑰呯嚎紼嬨?br>
銆銆鍊欐嵎鍏堢敓鏃╀簺鏃墮棿鍠滄涓篗DI紼嬪簭鐨勬瘡涓獥鍙e垱寤轟竴涓嚎紼嬶紝浠栧悗鏉ユ緞娓呬簡榪欎釜閿欒銆傚洜涓哄鏋滀負MDI紼嬪簭鐨勬瘡涓獥鍙i兘鍗曠嫭鍒涘緩涓涓嚎紼嬶紝鍦ㄧ獥鍙h繘琛屽垏鎹㈢殑鏃跺欙紝灝嗚繘琛岀嚎紼嬬殑涓婁笅鏂囧垏鎹紒
2.綰跨▼闂撮氫俊
銆銆MFC涓畾涔変簡緇ф壙鑷狢SyncObject綾葷殑CCriticalSection 銆丆CEvent銆丆Mutex銆丆Semaphore綾誨皝瑁呭拰綆鍖栦簡WIN32 API鎵鎻愪緵鐨勪復鐣屽尯銆佷簨浠躲佷簰鏂ュ拰淇″彿閲忋備嬌鐢ㄨ繖浜涘悓姝ユ満鍒訛紝蹇呴』鍖呭惈"Afxmt.h"澶存枃浠躲備笅鍥劇粰鍑轟簡綾葷殑緇ф壙鍏崇郴錛?br>
![]() |
class CSyncObject : public CObject { 銆DECLARE_DYNAMIC(CSyncObject) 銆// Constructor 銆public: 銆銆CSyncObject(LPCTSTR pstrName); 銆銆// Attributes 銆public: 銆銆operator HANDLE() const; 銆銆HANDLE m_hObject; 銆銆// Operations 銆銆virtual BOOL Lock(DWORD dwTimeout = INFINITE); 銆銆virtual BOOL Unlock() = 0; 銆銆virtual BOOL Unlock(LONG /* lCount */, LPLONG /* lpPrevCount="NULL" */) 銆銆{ return TRUE; } 銆銆// Implementation 銆public: 銆銆virtual ~CSyncObject(); 銆銆#ifdef _DEBUG 銆銆銆CString m_strName; 銆銆銆virtual void AssertValid() const; 銆銆銆virtual void Dump(CDumpContext& dc) const; 銆銆#endif 銆銆friend class CSingleLock; 銆銆friend class CMultiLock; }; |
class CThreadSafeWnd 銆銆~CThreadSafeWnd(){} 銆銆void SetWindow(CWnd *pwnd) 銆銆{ 銆銆銆m_pCWnd = pwnd; 銆銆} 銆銆void PaintBall(COLORREF color, CRect &rc); 銆private: 銆銆CWnd *m_pCWnd; 銆銆CCriticalSection m_CSect; }; void CThreadSafeWnd::PaintBall(COLORREF color, CRect &rc) { 銆CSingleLock csl(&m_CSect); 銆//緙虹渷鐨凾imeout鏄疘NFINITE錛屽彧鏈塵_Csect琚縺媧伙紝csl.Lock()鎵嶈兘榪斿洖 銆//true錛岃繖閲屼竴鐩寸瓑寰?br>銆if (csl.Lock()) ; 銆{ 銆銆// not necessary 銆銆//AFX_MANAGE_STATE(AfxGetStaticModuleState( )); 銆銆CDC *pdc = m_pCWnd->GetDC(); 銆銆CBrush brush(color); 銆銆CBrush *oldbrush = pdc->SelectObject(&brush); 銆銆pdc->Ellipse(rc); 銆銆pdc->SelectObject(oldbrush); 銆銆GdiFlush(); // don't wait to update the display 銆} } |
int array1[10], array2[10]; CMutexSection section; //鍒涘緩涓涓狢Mutex綾葷殑瀵硅薄 //璧嬪肩嚎紼嬫帶鍒跺嚱鏁?br>UINT EvaluateThread(LPVOID param) { 銆CSingleLock singlelock; 銆singlelock(§ion); 銆//浜掓枼鍖哄煙 銆singlelock.Lock(); 銆for (int i = 0; i < 10; i++) 銆銆array1[i] = i; 銆singlelock.Unlock(); } //鎷瘋礉綰跨▼鎺у埗鍑芥暟 UINT CopyThread(LPVOID param) { 銆CSingleLock singlelock; 銆singlelock(§ion); 銆//浜掓枼鍖哄煙 銆singlelock.Lock(); 銆for (int i = 0; i < 10; i++) 銆銆array2[i] = array1[i]; 銆singlelock.Unlock(); } } AfxBeginThread(EvaluateThread, NULL); //鍚姩璧嬪肩嚎紼?br>AfxBeginThread(CopyThread, NULL); //鍚姩鎷瘋礉綰跨▼ |
for (int i = 0; i < 10; i++) array1[i] = i; |
for (int i = 0; i < 10; i++) array2[i] = array1[i]; |
BOOL PostThreadMessage(DWORD idThread, // thread identifier UINT Msg, // message to post WPARAM wParam, // first message parameter LPARAM lParam // second message parameter |
3.綰跨▼涓庢秷鎭槦鍒?br>
銆銆鍦╓IN32涓紝姣忎竴涓嚎紼嬮兘瀵瑰簲鐫涓涓秷鎭槦鍒椼傜敱浜庝竴涓嚎紼嬪彲浠ヤ駭鐢熸暟涓獥鍙o紝鎵浠ュ茍涓嶆槸姣忎釜紿楀彛閮藉搴旂潃涓涓秷鎭槦鍒椼備笅鍒楀嚑鍙ヨ瘽搴旇浣滀負"瀹氱悊"琚浣忥細
銆銆"瀹氱悊" 涓
銆銆鎵鏈変駭鐢熺粰鏌愪釜紿楀彛鐨勬秷鎭紝閮藉厛鐢卞垱寤鴻繖涓獥鍙g殑綰跨▼澶勭悊錛?br>
銆銆"瀹氱悊" 浜?br>
銆銆Windows灞忓箷涓婄殑姣忎竴涓帶浠墮兘鏄竴涓獥鍙o紝鏈夊搴旂殑紿楀彛鍑芥暟銆?br>
銆銆娑堟伅鐨勫彂閫侀氬父鏈変袱縐嶆柟寮忥紝涓鏄疭endMessage錛屼竴鏄疨ostMessage錛屽叾鍘熷瀷鍒嗗埆涓猴細
LRESULT SendMessage(HWND hWnd, // handle of destination window 銆UINT Msg, // message to send 銆WPARAM wParam, // first message parameter 銆LPARAM lParam // second message parameter ); BOOL PostMessage(HWND hWnd, // handle of destination window 銆UINT Msg, // message to post 銆WPARAM wParam, // first message parameter 銆LPARAM lParam // second message parameter ); |
LRESULT SendMessageTimeout( 銆HWND hWnd, // handle of destination window 銆UINT Msg, // message to send 銆WPARAM wParam, // first message parameter 銆LPARAM lParam, // second message parameter 銆UINT fuFlags, // how to send the message 銆UINT uTimeout, // time-out duration 銆LPDWORD lpdwResult // return value for synchronous call ); |
class CMFCThreadApp : public CWinApp { 銆public: 銆銆CMFCThreadApp(); 銆銆// Overrides 銆銆// ClassWizard generated virtual function overrides 銆銆//{{AFX_VIRTUAL(CMFCThreadApp) 銆銆銆public: 銆銆銆銆virtual BOOL InitInstance(); 銆銆//}}AFX_VIRTUAL 銆銆// Implementation 銆public: 銆銆//{{AFX_MSG(CMFCThreadApp) 銆銆銆afx_msg void OnAppAbout(); 銆銆銆// NOTE - the ClassWizard will add and remove member functions here. 銆銆銆// DO NOT EDIT what you see in these blocks of generated code ! 銆銆//}}AFX_MSG 銆DECLARE_MESSAGE_MAP() }; |
CMFCThreadApp theApp; ///////////////////////////////////////////////////////////////////////////// // CMFCThreadApp initialization BOOL CMFCThreadApp::InitInstance() { 銆… 銆CMainFrame* pFrame = new CMainFrame; 銆m_pMainWnd = pFrame; 銆// create and load the frame with its resources 銆pFrame->LoadFrame(IDR_MAINFRAME,WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL,NULL); 銆// The one and only window has been initialized, so show and update it. 銆pFrame->ShowWindow(SW_SHOW); 銆pFrame->UpdateWindow(); 銆return TRUE; } |
#include "ChildView.h" class CMainFrame : public CFrameWnd { 銆public: 銆銆CMainFrame(); 銆protected: 銆銆DECLARE_DYNAMIC(CMainFrame) 銆銆// Attributes 銆public: 銆銆// Operations 銆public: 銆銆// Overrides 銆銆// ClassWizard generated virtual function overrides 銆銆//{{AFX_VIRTUAL(CMainFrame) 銆銆銆virtual BOOL PreCreateWindow(CREATESTRUCT& cs); 銆銆銆virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); 銆銆//}}AFX_VIRTUAL 銆銆// Implementation 銆public: 銆銆virtual ~CMainFrame(); 銆銆#ifdef _DEBUG 銆銆銆virtual void AssertValid() const; 銆銆銆virtual void Dump(CDumpContext& dc) const; 銆銆#endif 銆銆CChildView m_wndView; 銆銆// Generated message map functions 銆protected: 銆//{{AFX_MSG(CMainFrame) 銆銆afx_msg void OnSetFocus(CWnd *pOldWnd); 銆銆// NOTE - the ClassWizard will add and remove member functions here. 銆銆// DO NOT EDIT what you see in these blocks of generated code! 銆//}}AFX_MSG 銆DECLARE_MESSAGE_MAP() }; |
IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd) BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) 銆//{{AFX_MSG_MAP(CMainFrame) 銆銆// NOTE - the ClassWizard will add and remove mapping macros here. 銆銆// DO NOT EDIT what you see in these blocks of generated code ! 銆銆ON_WM_SETFOCUS() 銆//}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMainFrame construction/destruction CMainFrame::CMainFrame() { 銆// TODO: add member initialization code here } CMainFrame::~CMainFrame() {} BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { 銆if( !CFrameWnd::PreCreateWindow(cs) ) 銆銆return FALSE; 銆銆// TODO: Modify the Window class or styles here by modifying 銆銆// the CREATESTRUCT cs 銆cs.dwExStyle &= ~WS_EX_CLIENTEDGE; 銆cs.lpszClass = AfxRegisterWndClass(0); 銆return TRUE; } |
// CChildView window class CChildView : public CWnd { 銆// Construction 銆public: 銆銆CChildView(); 銆銆// Attributes 銆public: 銆銆// Operations 銆public: 銆銆// Overrides 銆銆// ClassWizard generated virtual function overrides 銆銆//{{AFX_VIRTUAL(CChildView) 銆銆銆protected: 銆銆銆銆virtual BOOL PreCreateWindow(CREATESTRUCT& cs); 銆銆//}}AFX_VIRTUAL 銆銆// Implementation 銆public: 銆銆virtual ~CChildView(); 銆銆// Generated message map functions 銆protected: 銆銆//{{AFX_MSG(CChildView) 銆銆銆afx_msg void OnPaint(); 銆銆//}}AFX_MSG 銆DECLARE_MESSAGE_MAP() }; ChildView.cpp鏂囦歡 // CChildView CChildView::CChildView() {} CChildView::~CChildView() {} BEGIN_MESSAGE_MAP(CChildView,CWnd ) //}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CChildView message handlers BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs) { 銆if (!CWnd::PreCreateWindow(cs)) 銆銆return FALSE; 銆cs.dwExStyle |= WS_EX_CLIENTEDGE; 銆cs.style &= ~WS_BORDER; 銆cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,::LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_WINDOW+1),NULL); 銆return TRUE; } void CChildView::OnPaint() { 銆CPaintDC dc(this); // device context for painting 銆// TODO: Add your message handler code here 銆// Do not call CWnd::OnPaint() for painting messages } |
![]() |
鎴戜滑鎻愬彇CWinApp綾誨師鍨嬬殑涓閮ㄥ垎錛?br>
class CWinApp : public CWinThread { 銆DECLARE_DYNAMIC(CWinApp) 銆public: 銆銆// Constructor 銆銆CWinApp(LPCTSTR lpszAppName = NULL);// default app name 銆銆// Attributes 銆銆// Startup args (do not change) 銆銆HINSTANCE m_hInstance; 銆銆HINSTANCE m_hPrevInstance; 銆銆LPTSTR m_lpCmdLine; 銆銆int m_nCmdShow; 銆銆// Running args (can be changed in InitInstance) 銆銆LPCTSTR m_pszAppName; // human readable name 銆銆LPCTSTR m_pszExeName; // executable name (no spaces) 銆銆LPCTSTR m_pszHelpFilePath; // default based on module path 銆銆LPCTSTR m_pszProfileName; // default based on app name 銆銆// Overridables 銆銆virtual BOOL InitApplication(); 銆銆virtual BOOL InitInstance(); 銆銆virtual int ExitInstance(); // return app exit code 銆銆virtual int Run(); 銆銆virtual BOOL OnIdle(LONG lCount); // return TRUE if more idle processing 銆銆virtual LRESULT ProcessWndProcException(CException* e,const MSG* pMsg); 銆public: 銆銆virtual ~CWinApp(); 銆protected: 銆銆DECLARE_MESSAGE_MAP() }; |
virtual BOOL InitApplication(); virtual BOOL InitInstance(); virtual int Run(); |
extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { 銆// call shared/exported WinMain 銆return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); } |
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { 銆ASSERT(hPrevInstance == NULL); 銆int nReturnCode = -1; 銆CWinThread* pThread = AfxGetThread(); 銆CWinApp* pApp = AfxGetApp(); 銆// AFX internal initialization 銆if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow)) 銆銆goto InitFailure; 銆// App global initializations (rare) 銆if (pApp != NULL && !pApp->InitApplication()) 銆銆goto InitFailure; 銆// Perform specific initializations 銆if (!pThread->InitInstance()) 銆{ 銆銆if (pThread->m_pMainWnd != NULL) 銆銆{ 銆銆銆TRACE0("Warning: Destroying non-NULL m_pMainWndn"); 銆銆銆pThread->m_pMainWnd->DestroyWindow(); 銆銆} 銆銆nReturnCode = pThread->ExitInstance(); 銆銆goto InitFailure; 銆} 銆nReturnCode = pThread->Run(); 銆InitFailure: 銆#ifdef _DEBUG 銆銆// Check for missing AfxLockTempMap calls 銆銆if (AfxGetModuleThreadState()->m_nTempMapLock != 0) 銆銆{ 銆銆銆TRACE1("Warning: Temp map lock count non-zero (%ld).n", AfxGetModuleThreadState()->m_nTempMapLock); 銆銆} 銆銆AfxLockTempMaps(); 銆銆AfxUnlockTempMaps(-1); 銆#endif 銆AfxWinTerm(); 銆return nReturnCode; } |
CWinThread* pThread = AfxGetThread(); CWinApp* pApp = AfxGetApp(); AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow) pApp->InitApplication() pThread->InitInstance() pThread->Run(); |
// main running routine until thread exits int CWinThread::Run() { 銆ASSERT_VALID(this); 銆// for tracking the idle time state 銆BOOL bIdle = TRUE; 銆LONG lIdleCount = 0; 銆// acquire and dispatch messages until a WM_QUIT message is received. 銆for (;;) 銆{ 銆銆// phase1: check to see if we can do idle work 銆銆while (bIdle && !::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE)) 銆銆{ 銆銆銆// call OnIdle while in bIdle state 銆銆銆if (!OnIdle(lIdleCount++)) 銆銆銆銆bIdle = FALSE; // assume "no idle" state 銆銆} 銆銆// phase2: pump messages while available 銆銆do 銆銆{ 銆銆銆// pump message, but quit on WM_QUIT 銆銆銆if (!PumpMessage()) 銆銆銆銆return ExitInstance(); 銆銆銆// reset "no idle" state after pumping "normal" message 銆銆銆if (IsIdleMessage(&m_msgCur)) 銆銆銆{ 銆銆銆銆bIdle = TRUE; 銆銆銆銆lIdleCount = 0; 銆銆銆} 銆銆} while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE)); 銆} 銆ASSERT(FALSE); // not reachable } |
///////////////////////////////////////////////////////////////////////////// // CWinThread implementation helpers BOOL CWinThread::PumpMessage() { 銆ASSERT_VALID(this); 銆if (!::GetMessage(&m_msgCur, NULL, NULL, NULL)) 銆{ 銆銆return FALSE; 銆} 銆// process this message 銆if(m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur)) 銆 銆return TRUE; } |
do while (::PeekMessage(...)); |
![]() ![]() ![]() |
DECLARE_MESSAGE_MAP() BEGIN_MESSAGE_MAP( 銆theClass, //Specifies the name of the class whose message map this is 銆baseClass //Specifies the name of the base class of theClass ) END_MESSAGE_MAP() |
DECLARE_MESSAGE_MAP() MFCThread.cpp鏂囦歡 BEGIN_MESSAGE_MAP(CMFCThreadApp, CWinApp) //{{AFX_MSG_MAP(CMFCThreadApp) ON_COMMAND(ID_APP_ABOUT, OnAppAbout) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG_MAP END_MESSAGE_MAP() MainFrm.cpp鏂囦歡 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) //{{AFX_MSG_MAP(CMainFrame) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code ! ON_WM_SETFOCUS() //}}AFX_MSG_MAP END_MESSAGE_MAP() ChildView.cpp鏂囦歡 BEGIN_MESSAGE_MAP(CChildView,CWnd ) //}AFX_MSG_MAP END_MESSAGE_MAP() |
CWinApp::CWinApp(LPCTSTR lpszAppName) { 銆if (lpszAppName != NULL) 銆銆m_pszAppName = _tcsdup(lpszAppName); 銆else 銆銆m_pszAppName = NULL; 銆// initialize CWinThread state 銆AFX_MODULE_STATE *pModuleState = _AFX_CMDTARGET_GETSTATE(); 銆AFX_MODULE_THREAD_STATE *pThreadState = pModuleState->m_thread; 銆ASSERT(AfxGetThread() == NULL); 銆pThreadState->m_pCurrentWinThread = this; 銆ASSERT(AfxGetThread() == this); 銆m_hThread = ::GetCurrentThread(); 銆m_nThreadID = ::GetCurrentThreadId(); 銆// initialize CWinApp state 銆ASSERT(afxCurrentWinApp == NULL); // only one CWinApp object please 銆pModuleState->m_pCurrentWinApp = this; 銆ASSERT(AfxGetApp() == this); 銆// in non-running state until WinMain 銆m_hInstance = NULL; 銆m_pszHelpFilePath = NULL; 銆m_pszProfileName = NULL; 銆m_pszRegistryKey = NULL; 銆m_pszExeName = NULL; 銆m_pRecentFileList = NULL; 銆m_pDocManager = NULL; 銆m_atomApp = m_atomSystemTopic = NULL; //寰蔣鎳掗錛熸垨鑰呬粬璁や負 銆//榪欐牱榪炵瓑鍚箟鏇存槑紜紵 銆m_lpCmdLine = NULL; 銆m_pCmdInfo = NULL; 銆// initialize wait cursor state 銆m_nWaitCursorCount = 0; 銆m_hcurWaitCursorRestore = NULL; 銆// initialize current printer state 銆m_hDevMode = NULL; 銆m_hDevNames = NULL; 銆m_nNumPreviewPages = 0; // not specified (defaults to 1) 銆// initialize DAO state 銆m_lpfnDaoTerm = NULL; // will be set if AfxDaoInit called 銆// other initialization 銆m_bHelpMode = FALSE; 銆m_nSafetyPoolSize = 512; // default size } |
m_hThread = ::GetCurrentThread();//theApp鐨勭嚎紼嬪彞鏌勭瓑浜庡綋鍓嶇嚎紼嬪彞鏌? m_nThreadID = ::GetCurrentThreadId();//theApp鐨勭嚎紼婭D絳変簬褰撳墠綰跨▼ID |
http://www-128.ibm.com/developerworks/cn/linux/l-mleak2/index.html
鍐呭瓨娉勬紡瀵逛簬C/C++紼嬪簭鍛樻潵璇翠篃鍙互綆椾綔鏄釜姘告亽鐨勮瘽棰樹簡鍚с傚湪Windows涓嬶紝MFC鐨勪竴涓緢鏈夌敤鐨勫姛鑳藉氨鏄兘鍦ㄧ▼搴忚繍琛岀粨鏉熸椂鎶ュ憡鏄惁鍙戠敓浜嗗唴瀛樻硠婕忋傚湪Linux涓嬶紝鐩稿鏉ヨ灝辨病鏈夐偅涔堝鏄撲嬌鐢ㄧ殑瑙e喅鏂規浜嗭細鍍弇patrol涔嬬被鐨勭幇鏈夊伐鍏鳳紝鏄撶敤鎬с侀檮鍔犲紑閿鍜屾ц兘閮戒笉鏄緢鐞嗘兂銆傛湰鏂囧疄鐜頒竴涓瀬鏄撲簬浣跨敤銆佽法騫沖彴鐨凜++鍐呭瓨娉勬紡媯嫻嬪櫒銆傚茍瀵圭浉鍏崇殑鎶鏈棶棰樹綔涓涓嬫帰璁ㄣ?/p>
瀵逛簬涓嬮潰榪欐牱鐨勪竴涓畝鍗曠▼搴弔est.cpp錛?/p>
int main() { int* p1 = new int; char* p2 = new char[10]; return 0; } |
鎴戜滑鐨勫熀鏈渶姹傚綋鐒舵槸瀵逛簬璇ョ▼搴忔姤鍛婂瓨鍦ㄤ袱澶勫唴瀛樻硠婕忋傝鍋氬埌榪欑偣鐨勮瘽錛岄潪甯哥畝鍗曪紝鍙鎶奷ebug_new.cpp涔熺紪璇戙侀摼鎺ヨ繘鍘誨氨鍙互浜嗐傚湪Linux涓嬶紝鎴戜滑浣跨敤錛?/p>
g++ test.cpp debug_new.cpp -o test |
杈撳嚭緇撴灉濡備笅鎵紺猴細
Leaked object at 0x805e438 (size 10, <Unknown>:0) Leaked object at 0x805e410 (size 4, <Unknown>:0) |
濡傛灉鎴戜滑闇瑕佹洿娓呮櫚鐨勬姤鍛婏紝涔熷緢綆鍗曪紝鍦╰est.cpp寮澶村姞涓琛?/p>
#include "debug_new.h" |
鍗沖彲銆傛坊鍔犺琛屽悗鐨勮緭鍑哄涓嬶細
Leaked object at 0x805e438 (size 10, test.cpp:5) Leaked object at 0x805e410 (size 4, test.cpp:4) |
闈炲父綆鍗曪紒
![]() ![]() |
![]()
|
鍦╪ew/delete鎿嶄綔涓紝C++涓虹敤鎴蜂駭鐢熶簡瀵筼perator new鍜宱perator delete鐨勮皟鐢ㄣ傝繖鏄敤鎴蜂笉鑳芥敼鍙樼殑銆俹perator new鍜宱perator delete鐨勫師鍨嬪涓嬫墍紺猴細
void *operator new(size_t) throw(std::bad_alloc); void *operator new[](size_t) throw(std::bad_alloc); void operator delete(void*) throw(); void operator delete[](void*) throw(); |
瀵逛簬"new int"錛岀紪璇戝櫒浼氫駭鐢熶竴涓皟鐢?operator new(sizeof(int))"錛岃屽浜?new char[10]"錛岀紪璇戝櫒浼氫駭鐢?operator new[](sizeof(char) * 10)"錛堝鏋渘ew鍚庨潰璺熺殑鏄竴涓被鍚嶇殑璇濓紝褰撶劧榪樿璋冪敤璇ョ被鐨勬瀯閫犲嚱鏁幫級銆傜被浼煎湴錛屽浜?delete ptr"鍜?delete[] ptr"錛岀紪璇戝櫒浼氫駭鐢?operator delete(ptr)"璋冪敤鍜?operator delete[](ptr)"璋冪敤錛堝鏋減tr鐨勭被鍨嬫槸鎸囧悜瀵硅薄鐨勬寚閽堢殑璇濓紝閭e湪operator delete涔嬪墠榪樿璋冪敤瀵硅薄鐨勬瀽鏋勫嚱鏁幫級銆傚綋鐢ㄦ埛娌℃湁鎻愪緵榪欎簺鎿嶄綔絎︽椂錛岀紪璇戠郴緇熻嚜鍔ㄦ彁渚涘叾瀹氫箟錛涜屽綋鐢ㄦ埛鑷繁鎻愪緵浜嗚繖浜涙搷浣滅鏃訛紝灝辮鐩栦簡緙栬瘧緋葷粺鎻愪緵鐨勭増鏈紝浠庤屽彲鑾峰緱瀵瑰姩鎬佸唴瀛樺垎閰嶆搷浣滅殑綺劇‘璺熻釜鍜屾帶鍒躲?/p>
鍚屾椂錛屾垜浠繕鍙互浣跨敤placement new鎿嶄綔絎︽潵璋冩暣operator new鐨勮涓恒傛墍璋損lacement new錛屾槸鎸囧甫鏈夐檮鍔犲弬鏁扮殑new鎿嶄綔絎︼紝姣斿錛屽綋鎴戜滑鎻愪緵浜嗕竴涓師鍨嬩負
void* operator new(size_t size, const char* file, int line); |
鐨勬搷浣滅鏃訛紝鎴戜滑灝卞彲浠ヤ嬌鐢?new("hello", 123) int"鏉ヤ駭鐢熶竴涓皟鐢?operator new(sizeof(int), "hello", 123)"銆傝繖鍙互鏄浉褰撶伒媧葷殑銆傚張濡傦紝C++鏍囧噯瑕佹眰緙栬瘧鍣ㄦ彁渚涚殑涓涓猵lacement new鎿嶄綔絎︽槸
void* operator new(size_t size, const std::nothrow_t&); |
鍏朵腑錛宯othrow_t閫氬父鏄竴涓┖緇撴瀯錛堝畾涔変負"struct nothrow_t {};"錛夛紝鍏跺敮涓鐩殑鏄彁渚涚紪璇戝櫒涓涓彲鏍規嵁閲嶈澆瑙勫垯璇嗗埆鍏蜂綋璋冪敤鐨勭被鍨嬨傜敤鎴蜂竴鑸畝鍗曞湴浣跨敤"new(std::nothrow) 綾誨瀷"錛坣othrow鏄竴涓猲othrow_t綾誨瀷鐨勫父閲忥級鏉ヨ皟鐢ㄨ繖涓猵lacement new鎿嶄綔絎︺傚畠涓庢爣鍑唍ew鐨勫尯鍒槸錛宯ew鍦ㄥ垎閰嶅唴瀛樺け璐ユ椂浼氭姏鍑哄紓甯革紝鑰?new(std::nothrow)"鍦ㄥ垎閰嶅唴瀛樺け璐ユ椂浼氳繑鍥炰竴涓┖鎸囬拡銆?/p>
瑕佹敞鎰忕殑鏄紝娌℃湁瀵瑰簲鐨?delete(std::nothrow) ptr"鐨勮娉曪紱涓嶈繃鍚庢枃浼氭彁鍒板彟涓涓浉鍏抽棶棰樸?/p>
瑕佽繘涓姝ヤ簡瑙d互涓婂叧浜嶤++璇█鐗規х殑淇℃伅錛岃鍙傞槄[Stroustrup1997]錛岀壒鍒槸6.2.6銆?0.4.11銆?5.6銆?9.4.5鍜孊.3.4鑺傘傝繖浜汣++璇█鐗規ф槸鐞嗚В鏈疄鐜扮殑鍏抽敭銆?/p>
![]() ![]() |
![]()
|
鍜屽叾瀹冧竴浜涘唴瀛樻硠婕忔嫻嬬殑鏂瑰紡綾諱技錛宒ebug_new涓彁渚涗簡operator new閲嶈澆錛屽茍浣跨敤浜嗗畯鍦ㄧ敤鎴風▼搴忎腑榪涜鏇挎崲銆俤ebug_new.h涓殑鐩稿叧閮ㄥ垎濡備笅錛?/p>
void* operator new(size_t size, const char* file, int line); void* operator new[](size_t size, const char* file, int line); #define new DEBUG_NEW #define DEBUG_NEW new(__FILE__, __LINE__) |
鎷夸笂闈㈠姞鍏ebug_new.h鍖呭惈鍚庣殑test.cpp鏉ヨ錛?new char[10]"鍦ㄩ澶勭悊鍚庝細鍙樻垚"new("test.cpp", 4) char[10]"錛岀紪璇戝櫒浼氭嵁姝や駭鐢熶竴涓?operator new[](sizeof(char) * 10, "test.cpp", 4)"璋冪敤銆傞氳繃鍦╠ebug_new.cpp涓嚜瀹氫箟"operator new(size_t, const char*, int)"鍜?operator delete(void*)"錛堜互鍙?operator new[]…"鍜?operator delete[]…"錛涗負閬垮厤琛屾枃绱禈錛屼互涓嬩笉鐗瑰埆鎸囧嚭錛岃鍒皁perator new鍜宱perator delete鍧囧悓鏃跺寘鍚暟緇勭増鏈級錛屾垜鍙互璺熻釜鎵鏈夌殑鍐呭瓨鍒嗛厤璋冪敤錛屽茍鍦ㄦ寚瀹氱殑媯鏌ョ偣涓婂涓嶅尮閰嶇殑new鍜宒elete鎿嶄綔榪涜鎶ヨ銆傚疄鐜板彲浠ョ浉褰撶畝鍗曪紝鐢╩ap璁板綍鎵鏈夊垎閰嶇殑鍐呭瓨鎸囬拡灝卞彲浠ヤ簡錛歯ew鏃跺線map閲屽姞涓涓寚閽堝強鍏跺搴旂殑淇℃伅錛宒elete鏃跺垹闄ゆ寚閽堝強瀵瑰簲鐨勪俊鎭紱delete鏃跺鏋渕ap閲屼笉瀛樺湪璇ユ寚閽堜負閿欒鍒犻櫎錛涚▼搴忛鍑烘椂濡傛灉map閲岃繕瀛樺湪鏈垹闄ょ殑鎸囬拡鍒欒鏄庢湁鍐呭瓨娉勬紡銆?/p>
涓嶈繃錛屽鏋滀笉鍖呭惈debug_new.h錛岃繖縐嶆柟娉曞氨璧蜂笉浜嗕綔鐢ㄤ簡銆備笉浠呭姝わ紝閮ㄥ垎鏂囦歡鍖呭惈debug_new.h錛岄儴鍒嗕笉鍖呭惈debug_new.h閮芥槸涓嶅彲琛岀殑銆傚洜涓鴻櫧鐒舵垜浠嬌鐢ㄤ簡涓ょ涓嶅悓鐨刼perator new --"operator new(size_t, const char*, int)"鍜?operator new(size_t)"-- 浣嗗彲鐢ㄧ殑"operator delete"榪樻槸鍙湁涓縐嶏紒浣跨敤鎴戜滑鑷畾涔夌殑"operator delete"錛屽綋鎴戜滑鍒犻櫎鐢?operator new(size_t)"鍒嗛厤鐨勬寚閽堟椂錛岀▼搴忓皢璁や負琚垹闄ょ殑鏄竴涓潪娉曟寚閽堬紒鎴戜滑澶勪簬涓涓袱闅懼鍦幫細瑕佷箞瀵硅繖縐嶆儏鍐典駭鐢熻鎶ワ紝瑕佷箞瀵歸噸澶嶅垹闄ゅ悓涓鎸囬拡涓ゆ涓嶄簣鎶ヨ錛氶兘涓嶆槸鍙帴鍙楃殑鑹ソ琛屼負銆?/p>
鐪嬫潵錛岃嚜瀹氫箟鍏ㄥ眬"operator new(size_t)"涔熸槸涓嶅彲閬垮厤鐨勪簡銆傚湪debug_new涓紝鎴戞槸榪欐牱鍋氱殑錛?/p>
void* operator new(size_t size) { return operator new(size, "<Unknown>", 0); } |
浣嗗墠闈㈡弿榪扮殑鏂瑰紡鍘誨疄鐜板唴瀛樻硠婕忔嫻嬪櫒錛屽湪鏌愪簺C++鐨勫疄鐜頒腑錛堝GCC 2.95.3涓甫鐨凷GI STL錛夊伐浣滄甯革紝浣嗗湪鍙﹀涓浜涘疄鐜頒腑浼氳帿鍚嶅叾濡欏湴宕╂簝銆傚師鍥犱篃涓嶅鏉傦紝SGI STL浣跨敤浜嗗唴瀛樻睜錛屼竴嬈″垎閰嶄竴澶х墖鍐呭瓨錛屽洜鑰屼嬌鍒╃敤map鎴愪負鍙兘錛涗絾鍦ㄥ叾浠栫殑瀹炵幇鍙兘娌¤繖鏍峰仛錛屽湪map涓坊鍔犳暟鎹細璋冪敤operator new錛岃宱perator new浼氬湪map涓坊鍔犳暟鎹紝浠庤屾瀯鎴愪竴涓寰幆錛屽鑷村唴瀛樻孩鍑猴紝搴旂敤紼嬪簭绔嬪嵆宕╂簝銆傚洜姝わ紝鎴戜滑涓嶅緱涓嶅仠姝嬌鐢ㄦ柟渚跨殑STL妯℃澘錛岃屼嬌鐢ㄦ墜宸ユ瀯寤虹殑鏁版嵁緇撴瀯錛?/p>
struct new_ptr_list_t { new_ptr_list_t* next; const char* file; int line; size_t size; }; |
鎴戞渶鍒濈殑瀹炵幇鏂規硶灝辨槸姣忔鍦ㄤ嬌鐢╪ew鍒嗛厤鍐呭瓨鏃訛紝璋冪敤malloc澶氬垎閰?sizeof(new_ptr_list_t) 涓瓧鑺傦紝鎶婂垎閰嶇殑鍐呭瓨鍏ㄩ儴涓叉垚涓涓竴涓摼琛紙鍒╃敤next瀛楁錛夛紝鎶婃枃浠跺悕銆佽鍙楓佸璞″ぇ灝忎俊鎭垎鍒瓨鍏ile銆乴ine鍜宻ize瀛楁涓紝鐒跺悗榪斿洖(malloc榪斿洖鐨勬寚閽?+ sizeof(new_ptr_list_t))銆傚湪delete鏃訛紝鍒欏湪閾捐〃涓悳绱紝濡傛灉鎵懼埌鐨勮瘽錛?char*)閾捐〃鎸囬拡 + sizeof(new_ptr_list_t) == 寰呴噴鏀劇殑鎸囬拡錛夛紝鍒欒皟鏁撮摼琛ㄣ侀噴鏀懼唴瀛橈紝鎵句笉鍒扮殑璇濇姤鍛婂垹闄ら潪娉曟寚閽堝茍abort銆?/p>
鑷充簬鑷姩媯嫻嬪唴瀛樻硠婕忥紝鎴戠殑鍋氭硶鏄敓鎴愪竴涓潤鎬佸叏灞瀵硅薄錛堟牴鎹瓹++鐨勫璞$敓鍛芥湡錛屽湪紼嬪簭鍒濆鍖栨椂浼氳皟鐢ㄨ瀵硅薄鐨勬瀯閫犲嚱鏁幫紝鍦ㄥ叾閫鍑烘椂浼氳皟鐢ㄨ瀵硅薄鐨勬瀽鏋勫嚱鏁幫級錛屽湪鍏舵瀽鏋勫嚱鏁頒腑璋冪敤媯嫻嬪唴瀛樻硠婕忕殑鍑芥暟銆傜敤鎴鋒墜宸ヨ皟鐢ㄥ唴瀛樻硠婕忔嫻嬪嚱鏁板綋鐒朵篃鏄彲浠ョ殑銆?/p>
鍩烘湰瀹炵幇澶т綋灝辨槸濡傛銆?/p>
![]() ![]() |
![]()
|
涓婅堪鏂規鏈鍒濆伐浣滃緱鐩稿綋濂斤紝鐩村埌鎴戝紑濮嬪垱寤哄ぇ閲忕殑瀵硅薄涓烘銆傜敱浜庢瘡嬈elete鏃墮渶瑕佸湪閾捐〃涓繘琛屾悳绱紝騫沖潎鎼滅儲嬈℃暟涓?閾捐〃闀垮害/2)錛岀▼搴忓緢蹇氨鎱㈠緱鍍忎箤榫熺埇銆傝櫧璇村彧鏄敤浜庤皟璇曪紝閫熷害澶參涔熸槸涓嶈兘鎺ュ彈鐨勩傚洜姝わ紝鎴戝仛浜嗕竴涓皬鏇存敼錛屾妸鎸囧悜閾捐〃澶撮儴鐨刵ew_ptr_list鏀規垚浜嗕竴涓暟緇勶紝涓涓璞℃寚閽堟斁鍦ㄥ摢涓涓摼琛ㄤ腑鍒欑敱瀹冪殑鍝堝笇鍊煎喅瀹氥?-鐢ㄦ埛鍙互鏇存敼瀹廌EBUG_NEW_HASH鍜孌EBUG_NEW_HASHTABLESIZE鐨勫畾涔夋潵璋冩暣debug_new鐨勮涓恒備粬浠殑褰撳墠鍊兼槸鎴戞祴璇曚笅鏉ユ瘮杈冩弧鎰忕殑瀹氫箟銆?/p>
浣跨敤涓垜浠彂鐜幫紝鍦ㄦ煇浜涚壒孌婃儏鍐典笅錛堣鐩存帴鍙傜湅debug_new.cpp涓叧浜嶥EBUG_NEW_FILENAME_LEN閮ㄥ垎鐨勬敞閲婏級錛屾枃浠跺悕鎸囬拡浼氬け鏁堛傚洜姝わ紝鐩墠鐨刣ebug_new鐨勭己鐪佽涓轟細澶嶅埗鏂囦歡鍚嶇殑澶?0涓瓧絎︼紝鑰屼笉鍙槸瀛樺偍鏂囦歡鍚嶇殑鎸囬拡銆傚彟澶栵紝璇鋒敞鎰忓師鍏坣ew_ptr_list_t鐨勯暱搴︿負16瀛楄妭錛岀幇鍦ㄦ槸32瀛楄妭錛岄兘鑳戒繚璇佸湪閫氬父鎯呭喌涓嬪唴瀛樺榻愩?/p>
姝ゅ錛屼負浜嗗厑璁哥▼搴忚兘鍜?new(std::nothrow) 涓璧峰伐浣滐紝鎴戜篃閲嶈澆浜唎perator new(size_t, const std::nothrow_t&) throw()錛涗笉鐒剁殑璇濓紝debug_new浼氳涓哄搴斾簬 new(nothrow) 鐨刣elete璋冪敤鍒犻櫎鐨勬槸涓涓潪娉曟寚閽堛傜敱浜巇ebug_new涓嶆姏鍑哄紓甯革紙鍐呭瓨涓嶈凍鏃剁▼搴忕洿鎺ユ姤璀﹂鍑猴級錛屾墍浠ヨ繖涓閲嶈澆鐨勬搷浣滃彧涓嶈繃鏄皟鐢?operator new(size_t) 鑰屽凡銆傝繖灝變笉鐢ㄥ璇翠簡銆?/p>
鍓嶉潰宸茬粡鎻愬埌錛岃寰楀埌綺劇‘鐨勫唴瀛樻硠婕忔嫻嬫姤鍛婏紝鍙互鍦ㄦ枃浠跺紑澶村寘鍚?debug_new.h"銆傛垜鐨勬儻甯稿仛娉曞彲浠ョ敤浣滃弬鑰冿細
#ifdef _DEBUG #include "debug_new.h" #endif |
鍖呭惈鐨勪綅緗簲褰撳敖鍙兘鏃╋紝闄ら潪璺熺郴緇熺殑澶存枃浠訛紙鍏稿瀷鎯呭喌鏄疭TL鐨勫ご鏂囦歡錛夊彂鐢熶簡鍐茬獊銆傚湪鏌愪簺鎯呭喌涓嬶紝鍙兘浼氫笉甯屾湜debug_new閲嶅畾涔塶ew錛岃繖鏃跺彲浠ュ湪鍖呭惈debug_new.h涔嬪墠瀹氫箟DEBUG_NEW_NO_NEW_REDEFINITION錛岃繖鏍風殑璇濓紝鍦ㄧ敤鎴峰簲鐢ㄧ▼搴忎腑搴斾嬌鐢╠ebug_new鏉ヤ唬鏇縩ew錛堥『渚挎彁涓鍙ワ紝娌℃湁瀹氫箟DEBUG_NEW_NO_NEW_REDEFINITION鏃朵篃鍙互浣跨敤debug_new浠f浛new錛夈傚湪婧愭枃浠朵腑涔熻灝辮榪欐牱鍐欙細
#ifdef _DEBUG #define DEBUG_NEW_NO_NEW_REDEFINITION #include "debug_new.h" #else #define debug_new new #endif |
騫跺湪闇瑕佽拷韙唴瀛樺垎閰嶇殑鏃跺欏叏閮ㄤ嬌鐢╠ebug_new錛堣冭檻浣跨敤鍏ㄥ眬鏇挎崲錛夈?/p>
鐢ㄦ埛鍙互閫夋嫨瀹氫箟DEBUG_NEW_EMULATE_MALLOC錛岃繖鏍穌ebug_new.h浼氫嬌鐢╠ebug_new鍜宒elete鏉ユā鎷焟alloc鍜宖ree鎿嶄綔錛屼嬌寰楃敤鎴風▼搴忎腑鐨刴alloc鍜宖ree鎿嶄綔涔熷彲浠ヨ璺熻釜銆傚湪浣跨敤鏌愪簺緙栬瘧鍣ㄧ殑鏃跺欙紙濡侱igital Mars C++ Compiler 8.29鍜孊orland C++ Compiler 5.5.1錛夛紝鐢ㄦ埛蹇呴』瀹氫箟NO_PLACEMENT_DELETE錛屽惁鍒欑紪璇戞棤娉曢氳繃銆傜敤鎴瘋繕鍙互浣跨敤涓や釜鍏ㄥ眬甯冨皵閲忔潵璋冩暣debug_new鐨勮涓猴細new_verbose_flag錛岀己鐪佷負false錛屽畾涔変負true鏃惰兘鍦ㄦ瘡嬈ew/delete鏃跺悜鏍囧噯閿欒杈撳嚭鏄劇ず璺熻釜淇℃伅錛沶ew_autocheck_flag錛岀己鐪佷負true錛屽嵆鍦ㄧ▼搴忛鍑烘椂鑷姩璋冪敤check_leaks媯鏌ュ唴瀛樻硠婕忥紝鏀逛負false鐨勮瘽鐢ㄦ埛蹇呴』鎵嬪伐璋冪敤check_leaks鏉ユ鏌ュ唴瀛樻硠婕忋?/p>
闇瑕佹敞鎰忕殑涓鐐規槸錛岀敱浜庤嚜鍔ㄨ皟鐢╟heck_leaks鏄湪debug_new.cpp涓殑闈欐佸璞℃瀽鏋勬椂錛屽洜姝や笉鑳戒繚璇佺敤鎴風殑鍏ㄥ眬瀵硅薄鐨勬瀽鏋勬搷浣滃彂鐢熷湪check_leaks璋冪敤涔嬪墠銆傚浜嶹indows涓婄殑MSVC錛屾垜浣跨敤浜?#pragma init_seg(lib)"鏉ヨ皟鏁村璞″垎閰嶉噴鏀劇殑欏哄簭錛屼絾寰堥仐鎲撅紝鎴戜笉鐭ラ亾鍦ㄥ叾浠栫殑涓浜涚紪璇戝櫒涓紙鐗瑰埆鏄紝鎴戞病鑳芥垚鍔熷湴鍦℅CC涓В鍐寵繖涓闂錛夋庝箞鍋氬埌榪欎竴鐐廣備負浜嗗噺灝戣鎶ヨ錛屾垜閲囧彇鐨勬柟寮忔槸鍦ㄨ嚜鍔ㄨ皟鐢ㄤ簡check_leaks涔嬪悗璁緉ew_verbose_flag涓簍rue錛涜繖鏍鳳紝灝辯畻璇姤鍛婁簡鍐呭瓨娉勬紡錛岄殢鍚庣殑delete鎿嶄綔榪樻槸浼氳鎵撳嵃鏄劇ず鍑烘潵銆傚彧瑕佹硠婕忔姤鍛婂拰delete鎶ュ憡鐨勫唴瀹逛竴鑷達紝鎴戜滑浠嶅彲浠ュ垽鏂嚭娌℃湁鍙戠敓鍐呭瓨娉勬紡銆?/p>
Debug_new涔熻兘媯嫻嬪鍚屼竴鎸囬拡閲嶅璋冪敤delete錛堟垨delete鏃犳晥鎸囬拡錛夌殑閿欒銆傜▼搴忓皢鏄劇ず閿欒鐨勬寚閽堝鹼紝騫跺己鍒惰皟鐢╝bort閫鍑恒?/p>
榪樻湁涓涓棶棰樻槸寮傚父澶勭悊銆傝繖鍊煎緱鐢ㄤ笓闂ㄧ殑涓鑺傛潵榪涜璇存槑銆?/p>
![]() ![]() |
![]()
|
鎴戜滑鐪嬩竴涓嬩互涓嬬殑綆鍗曠▼搴忕ず渚嬶細
#include <stdexcept> #include <stdio.h> void* operator new(size_t size, int line) { printf("Allocate %u bytes on line %d\\n", size, line); return operator new(size); } class Obj { public: Obj(int n); private: int _n; }; Obj::Obj(int n) : _n(n) { if (n == 0) { throw std::runtime_error("0 not allowed"); } } int main() { try { Obj* p = new(__LINE__) Obj(0); delete p; } catch (const std::runtime_error& e) { printf("Exception: %s\\n", e.what()); } } |
鐪嬪嚭浠g爜涓湁浠涔堥棶棰樹簡鍚楋紵瀹為檯涓婏紝濡傛灉鎴戜滑鐢∕SVC緙栬瘧鐨勮瘽錛岀紪璇戝櫒鐨勮鍛婁俊鎭凡緇忓憡璇夋垜浠彂鐢熶簡浠涔堬細
test.cpp(27) : warning C4291: 'void *__cdecl operator new(unsigned int,int)' : no matching operator delete found; memory will not be freed if initialization throws an exception |
濂斤紝鎶奷ebug_new.cpp閾炬帴榪涘幓銆傝繍琛岀粨鏋滃涓嬶細
Allocate 4 bytes on line 27 Exception: 0 not allowed Leaked object at 00342BE8 (size 4, <Unknown>:0) |
鍟婂摝錛屽唴瀛樻硠婕忎簡涓嶆槸錛?/p>
褰撶劧錛岃繖縐嶆儏鍐靛茍闈炲緢甯歌銆傚彲鏄紝闅忕潃瀵硅薄瓚婃潵瓚婂鏉傦紝璋佽兘澶熶繚璇佷竴涓璞$殑瀛愬璞$殑鏋勯犲嚱鏁版垨鑰呬竴涓璞″湪鏋勯犲嚱鏁頒腑璋冪敤鐨勬墍鏈夊嚱鏁伴兘涓嶄細鎶涘嚭寮傚父錛熷茍涓旓紝瑙e喅璇ラ棶棰樼殑鏂規硶騫朵笉澶嶆潅錛屽彧鏄渶瑕佺紪璇戝櫒瀵?C++ 鏍囧噯鏈夎緝濂芥敮鎸侊紝鍏佽鐢ㄦ埛瀹氫箟 placement delete 綆楃錛圼C++1998]錛?.3.4鑺傦紱緗戜笂鍙互鎵懼埌1996騫寸殑鏍囧噯鑽夋錛屾瘮濡備笅闈㈢殑緗戝潃 http://www.comnets.rwth-aachen.de/doc/c++std/expr.html#expr.new錛夈傚湪鎴戞祴璇曠殑緙栬瘧鍣ㄤ腑錛孏CC錛?.95.3鎴栨洿楂樼増鏈紝Linux/Windows錛夊拰MSVC錛?.0鎴栨洿楂樼増鏈級娌℃湁闂錛岃孊orland C++ Compiler 5.5.1鍜孌igital Mars C++ Compiler錛堝埌v8.38涓烘鐨勬墍鏈夌増鏈級鍒欎笉鏀寔璇ラ」鐗規с傚湪涓婇潰鐨勪緥瀛愪腑錛屽鏋滅紪璇戝櫒鏀寔鐨勮瘽錛屾垜浠氨闇瑕佸0鏄庡茍瀹炵幇 operator delete(void*, int) 鏉ュ洖鏀秐ew鍒嗛厤鐨勫唴瀛樸傜紪璇戝櫒涓嶆敮鎸佺殑璇濓紝闇瑕佷嬌鐢ㄥ畯璁╃紪璇戝櫒蹇界暐鐩稿叧鐨勫0鏄庡拰瀹炵幇銆傚鏋滆璁ヾebug_new鍦˙orland C++ Compiler 5.5.1鎴朌igital Mars C++ Compiler涓嬬紪璇戠殑璇濓紝鐢ㄦ埛蹇呴』瀹氫箟瀹廚O_PLACEMENT_DELETE錛涘綋鐒訛紝鐢ㄦ埛寰楄嚜宸辨敞鎰忓皬蹇冩瀯閫犲嚱鏁頒腑鎶涘嚭寮傚父榪欎釜闂浜嗐?
![]() ![]() |
![]()
|
IBM developerWorks涓婂垔杞戒簡媧惃鍏堢敓璁捐瀹炵幇鐨勪竴涓狶inux涓婄殑鍐呭瓨娉勬紡媯嫻嬫柟娉曪紙[媧惃2003]錛夈傛垜鐨勬柟妗堜笌鍏剁浉姣旓紝涓昏鍖哄埆濡備笅錛?/p>
浼樼偣錛?
緙虹偣錛?
鍙﹀錛岀幇鍦ㄥ凡瀛樺湪涓嶅皯鍟嗕笟鍜孫pen Source鐨勫唴瀛樻硠婕忔嫻嬪櫒錛屾湰鏂囦笉鎵撶畻涓涓鍐嶅仛姣旇緝銆侱ebug_new涓庡畠浠浉姣旓紝鍔熻兘涓婃葷殑鏉ヨ浠嶈緝寮憋紝浣嗘槸錛屽叾鑹ソ鐨勬槗鐢ㄦу拰璺ㄥ鉤鍙版с佷綆寤夌殑闄勫姞寮閿榪樻槸鍏鋒湁寰堝ぇ浼樺娍鐨勩?/p>
![]() ![]() |
![]()
|
浠ヤ笂孌佃惤鍩烘湰涓婂凡緇忚鏄庝簡debug_new鐨勪富瑕佺壒鐐廣備笅闈㈠仛涓涓皬灝忕殑鎬葷粨銆?/p>
閲嶈澆鐨勭畻絎︼細
鎻愪緵鐨勫嚱鏁幫細
鎻愪緵鐨勫叏灞鍙橀噺
鍙噸瀹氫箟鐨勫畯錛?
鎴戞湰浜鴻涓猴紝debug_new鐩墠鐨勪竴涓富瑕佺己闄鋒槸涓嶆敮鎸佸綰跨▼銆傚浜庢煇涓鐗瑰畾騫沖彴錛岃鍔犲叆澶氱嚎紼嬫敮鎸佸茍涓嶅洶闅撅紝闅懼氨闅懼湪閫氱敤涓婏紙褰撶劧錛屾潯浠剁紪璇戞槸涓涓姙娉曪紝铏界劧涓嶅浼橀泤錛夈傜瓑鍒癈++鏍囧噯涓寘鍚嚎紼嬫ā鍨嬫椂錛岃繖涓棶棰樹篃璁歌兘姣旇緝瀹岀編鍦拌В鍐沖惂銆傚彟涓涓姙娉曟槸浣跨敤鍍廱oost榪欐牱鐨勭▼搴忓簱涓殑綰跨▼灝佽綾伙紝涓嶈繃錛岃繖鍙堜細澧炲姞瀵瑰叾瀹冨簱鐨勪緷璧栨?-姣曠珶boost騫朵笉鏄疌++鏍囧噯鐨勪竴閮ㄥ垎銆傚鏋滈」鐩湰韜茍涓嶇敤boost錛屽崟涓轟簡榪欎竴涓洰鐨勪嬌鐢ㄥ彟澶栦竴涓▼搴忓簱浼間箮騫朵笉鍊煎緱銆傚洜姝わ紝鎴戣嚜宸辨殏鏃跺氨涓嶅仛榪欒繘涓姝ョ殑鏀硅繘浜嗐?/p>
鍙﹀涓涓彲鑳界殑淇敼鏄繚鐣欐爣鍑唎perator new鐨勫紓甯歌涓猴紝浣垮叾鍦ㄥ唴瀛樹笉瓚崇殑鎯呭喌涓嬫姏鍑哄紓甯革紙鏅氭儏鍐碉級鎴栨槸榪斿洖NULL錛坣othrow鎯呭喌錛夛紝鑰屼笉鏄儚鐜板湪涓鏍風粓姝㈢▼搴忚繍琛岋紙鍙傝debug_new.cpp鐨勬簮浠g爜錛夈傝繖涓鍋氭硶鐨勯毦搴︿富瑕佸湪浜庡悗鑰咃細鎴戞病鎯沖嚭浠涔堟柟娉曪紝鍙互淇濈暀 new(nothrow) 鐨勮娉曪紝鍚屾椂鑳藉鎶ュ憡鏂囦歡鍚嶅拰琛屽彿錛屽茍涓旇繕鑳藉浣跨敤鏅氱殑new銆備笉榪囷紝濡傛灉涓嶄嬌鐢ㄦ爣鍑嗚娉曪紝涓寰嬩嬌鐢╠ebug_new鍜宒ebug_new_nothrow鐨勮瘽錛岄偅榪樻槸闈炲父瀹規槗瀹炵幇鐨勩?/p>
濡傛灉澶у鏈夋敼榪涙剰瑙佹垨鍏跺畠鎯蟲硶鐨勮瘽錛屾榪庢潵淇¤璁恒?/p>
debug_new 鐨勬簮浠g爜鐩墠鍙互鍦?dbg_new.zip澶勪笅杞姐?
鍦ㄨ繖綃囨枃绔犵殑鍐欏畬涔嬪悗錛屾垜緇堜簬榪樻槸瀹炵幇浜嗕竴涓嚎紼嬪畨鍏ㄧ殑鐗堟湰銆傝鐗堟湰浣跨敤浜嗕竴涓交閲忕駭鐨勮法騫沖彴浜掓枼浣撶被fast_mutex錛堢洰鍓嶆敮鎸乄in32鍜孭OSIX綰跨▼錛屽湪浣跨敤GCC錛圠inux/MinGW錛夈丮SVC鏃惰兘閫氳繃鍛戒護琛屽弬鏁拌嚜鍔ㄦ嫻嬬嚎紼嬬被鍨嬶級銆傛湁鍏磋叮鐨勮瘽鍙湪 http://mywebpage.netscape.com/yongweiwu/dbg_new.tgz涓嬭澆銆?
[C++1998] ISO/IEC 14882. Programming Languages-C++, 1st Edition. International Standardization Organization, International Electrotechnical Commission, American National Standards Institute, and Information Technology Industry Council, 1998
[Stroustrup1997] Bjarne Stroustrup. The C++ Programming Language, 3rd Edition. Addison-Wesley, 1997
[媧惃2003] 媧惃銆?銆婂浣曞湪 linux 涓嬫嫻嬪唴瀛樻硠婕忋?/font>錛孖BM developerWorks 涓浗緗戠珯銆?
媯嫻嬪唴瀛樻硠闇茬殑宸ュ叿錛歞ebugnew
http://dev.csdn.net/article/58/58407.shtm
緗戜笂鏈変竴涓祦浼犵敋騫跨殑媯嫻嬪唴瀛樻硠闇茬殑宸ュ叿錛歞ebugnew(debugnew.h/debugnew.cpp)
鐢ㄦ硶寰堢畝鍗曪紝鎶奷ebugnew.cpp鏀懼湪欏圭洰閲屼竴璧風紪璇戯紝闇瑕佹嫻嬬殑鏂囦歡鎶奷ebugnew.h宓屽湪鏂囦歡鐨勬渶鍓嶉潰銆?br>
涓烘柟渚夸嬌鐢紝瀵規簮浠g爜鍋氫簡涓浜涘皬鐨勬敼鍔ㄣ?br>
涓嬮潰鏄竴浜涚畝鍗曠殑璇存槑錛?/p>
1銆乶ew 鐨勯噸杞?/font>
void* operator new (size_t size, const char* file, int line)錛涖銆銆銆銆銆銆銆鈶?br>void* operator new [] (size_t size, const char* file, int line)錛涖銆銆銆銆銆鈶?/p>
鍦ㄩ渶瑕佹嫻嬬殑鏂囦歡閲岋紝閲嶅畾涔塶ew
#define new new(__FILE__, __LINE__)
閫犳垚鐨勭粨鏋滐細
ClassName *p = new ClassName; => ClassName *p = new(__FILE__, __LINE__) ClassName;
// 瀹為檯浼氳皟鐢╲oid* operator new (size_t size, const char* file, int line)錛?/p>
ClassName **pp = new classname[count]; => ClassName **pp = new(__FILE__, __LINE__) ClassName[count];
// 瀹為檯浼氳皟鐢╲oid* operator new [] (size_t size, const char* file, int line)錛?/p>
榪欏叾瀹炴槸鍒╃敤浜唒lacement new鐨勮娉曪紝閫氳繃涓涓畝鍗曠殑瀹忥紝灝卞彲浠ユ妸鏅氱殑new鎿嶄綔瀵瑰簲鍒扮浉搴旂殑閲嶈澆( 鈶?鈶?)涓婂幓銆?/p>
2銆乨elete 鐨勯噸杞?/strong>
void operator delete (void* p, const char* file, int line); 鈶?br>void operator delete [] (void* p, const char* file, int line); 鈶?br>void operator delete (void* p); 鈶?br>void operator delete [] (void* p); 鈶?/p>
鍥犱負娌℃湁綾諱技浜巔lacement new鐨勮娉曪紝鎵浠ュ氨涓嶈兘鐢ㄤ竴涓畯鏉ユ浛鎹㈡浛鎹elete浜嗐傝璋冪敤甯︽湁鏇村淇℃伅鐨刣elete鎿嶄綔絎︼紝鍙兘淇敼婧愪唬鐮佷簡銆?br>delete p; => delete ( p, __FILE__, __LINE__ );
delete []pp; => delete [] ( pp, __FILE__, __LINE__ );
浣嗚繖涓伐浣滃緢鐑︾悙錛屽鏋滃茍涓嶉渶瑕佸浣欑殑淇℃伅鐨勮瘽錛岀畝鍗曞湴閲嶈澆delete( 鈶?鈶?)灝卞彲浠ヤ簡銆?/p>
3銆佹嫻嬪拰緇熻
紼嬪簭寮濮嬫椂錛屽湪debugnew.cpp涓細鍒涘緩涓涓狣ebugNewTracer瀵硅薄
鍦ㄩ噸杞界殑new鎿嶄綔絎? 鈶?鈶?)涓紝姣忎竴嬈″唴瀛樺垎閰嶉兘浼氳璁板綍錛岃屽湪delete( 鈶?鈶?鈶?鈶?)涓垯浼氬垹闄ょ浉搴旂殑璁板綍銆?br>褰撶▼搴忕粨鏉燂紝DebugNewTracer瀵硅薄琚攢姣侊紝瀹冪殑鏋愭瀯鍑芥暟浼歞ump鍓╀綑鐨勮褰曪紝榪欏氨鏄硠闇茬殑鍐呭瓨浜嗐?/p>
鍦ㄥ師鏈変唬鐮佺殑鍩虹涓婏紝澧炲姞浜嗚褰晄ize鐨勫姛鑳斤紝榪欐牱鍙互鍦ㄦ瘡嬈ew鍜宒elete鏃訛紝鐪嬪埌瀹為檯鍗犵敤鐨勫唴瀛樸傛墍鏈変俊鎭彲浠ump鍑烘潵錛屼篃鍙互鍐欏叆log銆?br>
5銆佹簮浠g爜
********************************************************
debugnew.h:
/*
filename: debugnew.h
This code is based on code retrieved from a web site. The
author was not identified, so thanks go to anonymous.
This is used to substitute a version of the new operator that
can be used for debugging memory leaks. To use it:
- In any (all?) code files #include debugnew.h. Make sure all
system files (i.e. those in <>'s) are #included before
debugnew.h, and that any header files for your own code
are #included after debugnew.h. The reason is that some
system files refer to ::new, and this will not compile
if debugnew is in effect. You may still have problems
if any of your own code refers to ::new, or if any
of your own files #include system files that use ::new
and which have not already been #included before
debugnew.h.
- Add debugnew.cpp to the CodeWarrior project or compile
it into your Linux executable. If debugnew.cpp is in the
project, then debugnew.h must be #included in at least
one source file
*/
#ifndef __DEBUGNEW_H__
#define __DEBUGNEW_H__
#include <map>
#define LOG_FILE
#if defined(LOG_FILE)
#define LOG_FILE_NAME "./debugnew.log"
#endif
void* operator new (std::size_t size, const char* file, int line);
void operator delete (void* p, const char* name, int line);
void* operator new [] (std::size_t size, const char* file, int line);
void operator delete [] (void* p, const char* name, int line);
class DebugNewTracer {
private:
class Entry {
public:
Entry (char const* file, int line) : _file (file), _line (line) {}
Entry (char const* file, int line, int size) : _file (file), _line (line), _size (size) {}
Entry () : _file (0), _line (0), _size (0) {}
const char* File () const { return _file; }
int Line () const { return _line; }
size_t Size () const { return _size; }
private:
char const* _file;
int _line;
size_t _size;
};
class Lock {
public:
Lock (DebugNewTracer & DebugNewTracer) : _DebugNewTracer (DebugNewTracer) {
_DebugNewTracer.lock ();
}
~Lock () {
_DebugNewTracer.unlock ();
}
private:
DebugNewTracer & _DebugNewTracer;
};
typedef std::map<void*, Entry>::iterator iterator;
friend class Lock;
public:
DebugNewTracer ();
~DebugNewTracer ();
void Add (void* p, const char* file, int line);
void Add (void* p, const char* file, int line, size_t size);
void Remove (void* p);
void Dump ();
static bool Ready;
private:
void lock () { _lockCount++; }
void unlock () { _lockCount--; }
private:
std::map<void*, Entry> _map;
int _lockCount;
size_t _totalsize;
#if defined(LOG_FILE)
FILE* _logfp;
#endif
};
// The file that implements class DebugNewTracer
// does NOT want the word "new" expanded.
// The object DebugNewTrace is defined in that
// implementation file but only declared in any other file.
#ifdef DEBUGNEW_CPP
DebugNewTracer DebugNewTrace;
#else
#define new new(__FILE__, __LINE__)
extern DebugNewTracer DebugNewTrace;
#endif
#endif//#ifndef __DEBUGNEW_H__
********************************************************
debugnew.cpp:
/*
filename: debugnew.cpp
This is used to substitute a version of the new operator that
can be used for debugging memory leaks. In any (all?) code
files #include debugnew.h. Add debugnew.cpp to the project.
*/
#include <iostream>
#include <map>
using namespace std;
// This disables macro expansion of "new".
// This statement should only appear in this file.
#define DEBUGNEW_CPP
#include "debugnew.h"
DebugNewTracer::DebugNewTracer () : _lockCount (0)
{
// Once this object is constructed all calls to
// new should be traced.
Ready = true;
_totalsize = 0;
#if defined(LOG_FILE)
if( (_logfp=fopen(LOG_FILE_NAME,"wt")) == NULL )
{
printf(" Error! file: debugnew.log can not open@!\n");
return;
}
fprintf(_logfp,"new, delete list:\n");
fflush(_logfp);
#endif
}
void DebugNewTracer::Add (void* p, const char* file, int line)
{
// Tracing must not be done a second time
// while it is already
// in the middle of executing
if (_lockCount > 0)
return;
// Tracing must be disabled while the map
// is in use in case it calls new.
DebugNewTracer::Lock lock (*this);
_map [p] = Entry (file, line);
}
void DebugNewTracer::Add (void* p, const char* file, int line, size_t size)
{
// Tracing must not be done a second time
// while it is already
// in the middle of executing
if (_lockCount > 0)
return;
// Tracing must be disabled while the map
// is in use in case it calls new.
DebugNewTracer::Lock lock (*this);
#if 1
//´Óȫ·¾¶ÖÐÌáÈ¡ÎļþÃû
//linuxϵÄgcc,__FILE__½ö½ö°üÀ¨ÎļþÃû£¬windowsϵÄvc,__FILE__°üÀ¨È«Â·¾¶,ËùÒÔÓÐÕâÑùµÄ´¦Àí
file = strrchr(file,'\\')== NULL?file:strrchr(file,'\\')+1;
#endif
_map [p] = Entry (file, line, size);
_totalsize += size;
#if defined(LOG_FILE)
fprintf(_logfp,"*N p = 0x%08x, size = %6d, %-22s, Line: %4d. totalsize =%8d\n", p, size, file, line, _totalsize);
fflush(_logfp);
#endif
}
void DebugNewTracer::Remove (void* p)
{
// Tracing must not be done a second time
// while it is already
// in the middle of executing
if (_lockCount > 0)
return;
// Tracing must be disabled while the map
// is in use in case it calls new.
DebugNewTracer::Lock lock (*this);
iterator it = _map.find (p);
if (it != _map.end ())
{
size_t size = (*it).second.Size();
_totalsize -= size;
#if defined(LOG_FILE)
fprintf(_logfp,"#D p = 0x%08x, size = %6u.%39stotalsize =%8d\n", p, size, "----------------------------------- ", _totalsize );
fflush(_logfp);
#endif
_map.erase (it);
}
else
{
#if defined(LOG_FILE)
fprintf(_logfp,"#D p = 0x%08x. error point!!!\n", p );
fflush(_logfp);
#endif
}
}
DebugNewTracer::~DebugNewTracer ()
{
// Trace must not be called if Dump indirectly
// invokes new, so it must be disabled before
// Dump is called. After this destructor executes
// any other global objects that get destructed
// should not do any tracing.
Ready = false;
Dump ();
#if defined(LOG_FILE)
fclose(_logfp);
#endif
}
// If some global object is destructed after DebugNewTracer
// and if that object calls new, it should not trace that
// call to new.
void DebugNewTracer::Dump ()
{
if (_map.size () != 0)
{
std::cout << _map.size () << " memory leaks detected\n";
#if defined(LOG_FILE)
fprintf(_logfp, "\n\n***%d memory leaks detected\n", _map.size ());
fflush(_logfp);
#endif
for (iterator it = _map.begin (); it != _map.end (); ++it)
{
char const * file = it->second.File ();
int line = it->second.Line ();
int size = it->second.Size ();
std::cout << file << ", " << line << std::endl;
#if defined(LOG_FILE)
fprintf(_logfp,"%s, %d, size=%d\n", file, line, size);
fflush(_logfp);
#endif
}
}
else
{
std::cout << "no leaks detected\n";
#if defined(LOG_FILE)
fprintf(_logfp,"no leaks detected\n");
fflush(_logfp);
#endif
}
}
// If some global object is constructed before DebugNewTracer
// and if that object calls new, it should not trace that
// call to new.
bool DebugNewTracer::Ready = false;
void* operator new (size_t size, const char* file, int line)
{
void * p = malloc (size);
if (DebugNewTracer::Ready)
DebugNewTrace.Add (p, file, line, size);
return p;
}
void operator delete (void* p, const char* file, int line)
{
file = 0; // avoid a warning about argument not used in function
line = 0; // avoid a warning about argument not used in function
if (DebugNewTracer::Ready)
DebugNewTrace.Remove (p);
free (p);
}
void* operator new [] (size_t size, const char* file, int line)
{
void * p = malloc (size);
if (DebugNewTracer::Ready)
DebugNewTrace.Add (p, file, line, size);
return p;
}
void operator delete [] (void* p, const char* file, int line)
{
file = 0; // avoid a warning about argument not used in function
line = 0; // avoid a warning about argument not used in function
if (DebugNewTracer::Ready)
DebugNewTrace.Remove (p);
free (p);
}
void* operator new (size_t size)
{
void * p = malloc (size);
// When uncommented these lines cause entries in the map for calls to new
// that were not altered to the debugnew version. These are likely calls
// in library functions and the presence in the dump of these entries
// is usually misleading.
// if (DebugNewTracer::Ready)
// DebugNewTrace.Add (p, "?", 0);
return p;
}
void operator delete (void* p)
{
if (DebugNewTracer::Ready)
DebugNewTrace.Remove (p);
free (p);
}
//add by yugang
void operator delete [] (void* p)
{
if (DebugNewTracer::Ready)
DebugNewTrace.Remove (p);
free (p);
}
涓轟粈涔堣寮曞叆铏氭嫙緇ф壙錛?/span>
铏氭嫙緇ф壙鍦ㄤ竴鑸殑搴旂敤涓緢灝戠敤鍒幫紝鎵浠ヤ篃寰寰琚拷瑙嗭紝榪欎篃涓昏鏄洜涓哄湪C++涓紝澶氶噸緇ф壙鏄笉鎺ㄨ崘鐨勶紝涔熷茍涓嶅父鐢紝鑰屼竴鏃︾寮浜嗗閲嶇戶鎵匡紝铏氭嫙緇ф壙灝卞畬鍏ㄥけ鍘諱簡瀛樺湪鐨勫繀瑕侊紙鍥犱負榪欐牱鍙細闄嶄綆鏁堢巼鍜屽崰鐢ㄦ洿澶氱殑絀洪棿錛屽叧浜庤繖涓鐐癸紝鎴戣嚜宸辮繕娌℃湁澶娣卞埢鐨勭悊瑙o紝鏈夊叴瓚g殑鍙互鐪嬬綉緇滀笂鐧芥潹鐨勪綔鍝?/span>銆?/span>RTTI銆佽櫄鍑芥暟鍜岃櫄鍩?span>綾葷殑寮閿鍒嗘瀽鍙婁嬌鐢ㄦ寚瀵?span>銆?/span>錛岃瀹炶瘽鎴戠洰鍓嶈繕娌$湅寰楀緢鏄庣櫧錛岄珮浜哄彲浠ユ寚鐐逛笅鎴戯級銆?/span>
浠ヤ笅闈㈢殑涓涓緥瀛愪負渚嬶細
#include <iostream.h>
#include <memory.h>
class CA
{
int k; //濡傛灉鍩虹被娌℃湁鏁版嵁鎴愬憳錛屽垯鍦ㄨ繖閲屽閲嶇戶鎵跨紪璇戜笉浼氬嚭鐜頒簩涔夋?/span>
public:
void f() {cout << "CA::f" << endl;}
};
class CB : public CA
{
};
class CC : public CA
{
};
class CD : public CB, public CC
{
};
void main()
{
CD d;
d.f();
}
褰撶紪璇戜笂榪頒唬鐮佹椂錛屾垜浠細鏀跺埌濡備笅鐨勯敊璇彁紺猴細
error C2385: 'CD::f' is ambiguous
鍗崇紪璇戝櫒鏃犳硶紜畾浣犲湪d.f()涓璋冪敤鐨勫嚱鏁?/span>f鍒板簳鏄摢涓涓傝繖閲屽彲鑳戒細璁╀漢瑙夊緱鏈変簺濂囨紝鍛藉悕鍙畾涔変簡涓涓?/span>CA::f錛屾棦鐒跺ぇ瀹墮兘媧劇敓鑷?/span>CA錛岄偅鑷劧灝辨槸璋冪敤鐨?/span>CA::f錛屼負浠涔堣繕鏃犳硶紜畾鍛紵
榪欐槸鍥犱負緙栬瘧鍣ㄥ湪榪涜緙栬瘧鐨勬椂鍊欙紝闇瑕佺‘瀹氬瓙綾葷殑鍑芥暟瀹氫箟錛屽CA::f鏄‘瀹氱殑錛岄偅涔堝湪緙栬瘧CB銆?/span>CC鏃惰繕闇瑕佸湪緙栬瘧鍣ㄧ殑璇硶鏍戜腑鐢熸垚CB::f錛?/span>CC::f絳夋爣璇嗭紝閭d箞錛屽湪緙栬瘧CD鐨勬椂鍊欙紝鐢變簬CB銆?/span>CC閮芥湁涓涓嚱鏁?/span>f錛屾鏃訛紝緙栬瘧鍣ㄥ皢璇曞浘鐢熸垚榪欎袱涓?/span>CD::f鏍囪瘑錛屾樉鐒惰繖鏃跺氨瑕佹姤閿欎簡銆傦紙褰撴垜浠笉浣跨敤CD::f鐨勬椂鍊欙紝浠ヤ笂鏍囪瘑閮戒笉浼氱敓鎴愶紝鎵浠ワ紝濡傛灉鍘繪帀d.f()涓鍙ワ紝紼嬪簭灝嗛『鍒╅氳繃緙栬瘧錛?/span>
瑕佽В鍐寵繖涓棶棰橈紝鏈変袱涓柟娉曪細
1銆侀噸杞藉嚱鏁?/span>f()錛氭鏃剁敱浜庢垜浠槑紜畾涔変簡CD::f錛岀紪璇戝櫒媯鏌ュ埌CD::f()璋冪敤鏃跺氨鏃犻渶鍐嶅儚涓婇潰涓鏍峰幓閫愮駭鐢熸垚CD::f鏍囪瘑浜嗭紱
姝ゆ椂CD鐨勫厓绱犵粨鏋勫涓嬶細
|CB(CA)|
|CC(CA)|
鏁呮鏃剁殑sizeof(CD) = 8;錛?/span>CB銆?/span>CC鍚勬湁涓涓厓绱?/span>k錛?/span>
2銆佷嬌鐢ㄨ櫄鎷熺戶鎵匡細铏氭嫙緇ф壙鍙堢О浣滃叡浜戶鎵匡紝榪欑鍏變韓鍏跺疄涔熸槸緙栬瘧鏈熼棿瀹炵幇鐨勶紝褰撲嬌鐢ㄨ櫄鎷熺戶鎵挎椂錛屼笂闈㈢殑紼嬪簭灝嗗彉鎴愪笅闈㈢殑褰㈠紡錛?/span>
#include <iostream.h>
#include <memory.h>
class CA
{
int k;
public:
void f() {cout << "CA::f" << endl;}
};
class CB : virtual public CA //涔熸湁涓縐嶅啓娉曟槸class CB : public virtual CA
{ //瀹為檯涓婅繖涓ょ鏂規硶閮藉彲浠?/span>
};
class CC : virtual public CA
{
};
class CD : public CB, public CC
{
};
void main()
{
CD d;
d.f();
}
姝ゆ椂錛屽綋緙栬瘧鍣ㄧ‘瀹?/span>d.f()璋冪敤鐨勫叿浣撳惈涔夋椂錛屽皢鐢熸垚濡備笅鐨?/span>CD緇撴瀯錛?/span>
|CB|
|CC|
|CA|
鍚屾椂錛屽湪CB銆?/span>CC涓兘鍒嗗埆鍖呭惈浜嗕竴涓寚鍚?/span>CA鐨勮櫄鍩虹被鎸囬拡鍒楄〃vbptr錛?/span>virtual base table pointer錛夛紝鍏朵腑璁板綍鐨勬槸浠?/span>CB銆?/span>CC鐨勫厓绱犲埌CA鐨勫厓绱犱箣闂寸殑鍋忕Щ閲忋傛鏃訛紝涓嶄細鐢熸垚鍚勫瓙綾葷殑鍑芥暟f鏍囪瘑錛岄櫎闈炲瓙綾婚噸杞戒簡璇ュ嚱鏁幫紝浠庤岃揪鍒?#8220;鍏變韓”鐨勭洰鐨勶紙榪欓噷鐨勫叿浣撳唴瀛樺竷灞錛屽彲浠ュ弬鐪嬮捇鐭沖瀷緇ф壙鍐呭瓨甯冨眬錛屽湪鐧芥潹鐨勯偅綃囨枃绔犱腑涔熸湁錛夈?/span>
涔熸鍥犳錛屾鏃剁殑sizeof(CD) = 12錛堜袱涓?/span>vbptr + sizoef(int)錛?/span>;
鍙︽敞錛?/span>
濡傛灉CB錛?/span>CC涓悇瀹氫箟涓涓?/span>int鍨嬪彉閲忥紝鍒?/span>sizeof(CD)灝卞彉鎴?/span>20(涓や釜vbptr + 3涓?/span>sizoef(int)
濡傛灉CA涓坊鍔犱竴涓?/span>virtual void f1(){}錛?/span>sizeof(CD) = 16錛堜袱涓?/span>vbptr + sizoef(int)+vptr錛?/span>;
鍐嶆坊鍔?/span>virtual void f2(){}錛?/span>sizeof(CD) = 16涓嶅彉銆傚師鍥犲涓嬫墍紺猴細甯︽湁铏氬嚱鏁扮殑綾伙紝鍏跺唴瀛樺竷灞涓婂寘鍚竴涓寚鍚戣櫄鍑芥暟鍒楄〃鐨勬寚閽堬紙vptr錛夛紝榪欒窡鏈夊嚑涓櫄鍑芥暟鏃犲叧銆?/span>
浠ヤ笂鍐呭娑夊強鍒扮被瀵硅薄鍐呭瓨甯冨眬闂錛屾湰浜鴻繕闅句互鍋氳繃澶氬睍寮錛屽厛璐磋繖涔堝錛屾湰綃囨枃绔犲彧鏄冭檻瀵逛簬铏氭嫙緇ф壙榪涜鍏ラ棬錛岃嚦浜庢晥鐜囥佸簲鐢ㄧ瓑鏈綔灞曞紑銆傛湰鏂囧湪緗戜笂鏂囩珷鍩虹涓婁慨鏀逛簡涓嬭屽緱姝ょ瘒錛屽師鏂囪澆浜?/span>http://blog.csdn.net/billdavid/archive/2004/06/23/24317.aspx
鍙﹀鍏充簬铏氱戶鎵垮拰铏氬熀綾葷殑璁ㄨ錛屽崥瀹㈠洯鏈夌瘒鏂囩珷銆?/span>铏氱戶鎵夸笌铏氬熀綾葷殑鏈川銆嬶紝鎬葷粨寰楁洿涓鴻緇嗕竴鐐廣?/span>