❶ C++ 編譯時如何根據是否存在無參構造函數決定是否調用該構造函數
根據你創建對象的方式,決定調用構造函數的類型
例如BASE a(10) BASE a
前者調用有一個參數的構造函數,後者調用無參數的構造函數
在類的聲明中如果你沒有寫構造函數,編譯器會為你提供一個無參數的默認構造函數
如果你聲明了構造函數,編譯器就不會給你提供無參數的構造函數
例如
class BASE {
}
class BASE{
BASE(int){}
}
前者會默認生成一個BASE(){}的構造函數、
後者則不會
如果你用後者去聲明一個對象
那麼你就必須為這個對象提供參數
如果你使用BASE a;聲明對象,就會報錯。
因為編譯器沒有給提供無參數的構造函數
希望我的解答能夠幫助到你,如滿意,請採納
❷ C璇璦閲岄潰鏋勯犲嚱鏁板拰鏋愭瀯鍑芥暟鐨勮繍鐢ㄥ姙娉
銆銆鎽 瑕侊細鏋勯犲嚱鏁頒笌鏋愭瀯鍑芥暟鏄涓涓綾諱腑鐪嬩技杈冧負綆鍗曠殑涓ょ被鍑芥暟錛屼絾鍦ㄥ疄闄呰繍鐢ㄨ繃紼嬩腑鎬諱細鍑虹幇涓浜涙剰鎯充笉鍒扮殑榪愯岄敊璇銆傛湰鏂囧皢杈冪郴緇熺殑浠嬬粛鏋勯犲嚱鏁頒笌鏋愭瀯鍑芥暟鐨勫師鐞嗗強鍦–#涓鐨勮繍鐢錛屼互鍙婂湪浣跨敤榪囩▼涓闇瑕佹敞鎰忕殑鑻ュ共浜嬮」銆
銆銆鍏抽敭瀛楋細鏋勯犲嚱鏁幫紱鏋愭瀯鍑芥暟錛涘瀮鍦懼洖鏀跺櫒錛涢潪鎵樼¤祫婧愶紱鎵樼¤祫婧
銆銆 涓錛庢瀯閫犲嚱鏁頒笌鏋愭瀯鍑芥暟鐨勫師鐞
銆銆浣滀負姣擟鏇村厛榪涚殑璇璦錛孋#鎻愪緵浜嗘洿濂界殑鏈哄埗鏉ュ炲己紼嬪簭鐨勫畨鍏ㄦс侰#緙栬瘧鍣ㄥ叿鏈変弗鏍肩殑綾誨瀷瀹夊叏媯鏌ュ姛鑳斤紝瀹冨嚑涔庤兘鎵懼嚭紼嬪簭涓鎵鏈夌殑璇娉曢棶棰橈紝榪欑殑紜甯浜嗙▼搴忓憳鐨勫ぇ蹇欍備絾鏄紼嬪簭閫氳繃浜嗙紪璇戞鏌ュ苟涓嶈〃紺洪敊璇宸茬粡涓嶅瓨鍦ㄤ簡錛屽湪鈥滈敊璇鈥濈殑澶у跺涵閲岋紝鈥滆娉曢敊璇鈥濈殑鍦頒綅鍙鑳界畻鏄鍐板北涓瑙掋傜駭鍒楂樼殑閿欒閫氬父闅愯棌寰楀緢娣憋紝涓嶅規槗鍙戠幇銆
銆銆鏍規嵁緇忛獙錛屼笉灝戦毦浠ュ療瑙夌殑紼嬪簭閿欒鏄鐢變簬鍙橀噺娌℃湁琚姝g『鍒濆嬪寲鎴栨竻闄ら犳垚鐨勶紝鑰屽垵濮嬪寲鍜屾竻闄ゅ伐浣滃緢瀹規槗琚浜洪仐蹇樸傚井杞鍒╃敤闈㈠悜瀵硅薄鐨勬傚康鍦ㄨ捐C#璇璦鏃跺厖鍒嗚冭檻浜嗚繖涓闂棰樺苟寰堝ソ鍦頒簣浠ヨВ鍐籌細鎶婂硅薄鐨勫垵濮嬪寲宸ヤ綔鏀懼湪鏋勯犲嚱鏁頒腑錛屾妸娓呴櫎宸ヤ綔鏀懼湪鏋愭瀯鍑芥暟涓銆傚綋瀵硅薄琚鍒涘緩鏃訛紝鏋勯犲嚱鏁拌鑷鍔ㄦ墽琛屻傚綋瀵硅薄娑堜骸鏃訛紝鏋愭瀯鍑芥暟琚鑷鍔ㄦ墽琛屻傝繖鏍峰氨涓嶇敤鎷呭績蹇樿板硅薄鐨勫垵濮嬪寲鍜屾竻闄ゅ伐浣溿
銆銆 浜岋紟鏋勯犲嚱鏁板湪C#涓鐨勮繍鐢
銆銆鏋勯犲嚱鏁扮殑鍚嶅瓧涓嶈兘闅忎究璧鳳紝蹇呴』璁╃紪璇戝櫒璁ゅ緱鍑烘墠鍙浠ヨ鑷鍔ㄦ墽琛屻傚畠鐨勫懡鍚嶆柟娉曟棦綆鍗曞張鍚堢悊錛氳╂瀯閫犲嚱鏁頒笌綾誨悓鍚嶃傞櫎浜嗗悕瀛楀栵紝鏋勯犲嚱鏁扮殑鍙︿竴涓鐗瑰埆涔嬪勬槸娌℃湁榪斿洖鍊肩被鍨嬶紝榪欎笌榪斿洖鍊肩被鍨嬩負void鐨勫嚱鏁頒笉鍚屻傚傛灉瀹冩湁榪斿洖鍊肩被鍨嬶紝閭d箞緙栬瘧鍣ㄥ皢涓嶇煡鎵鎺銆傚湪浣犲彲浠ヨ塊棶涓涓綾葷殑鏂規硶銆佸睘鎬ф垨浠諱綍鍏跺畠涓滆タ涔嬪墠錛 絎涓鏉℃墽琛岀殑璇鍙ユ槸鍖呭惈鏈夌浉搴旂被鐨勬瀯閫犲嚱鏁般傜敋鑷充綘鑷宸變笉鍐欎竴涓鏋勯犲嚱鏁幫紝涔熶細鏈変竴涓緙虹渷鏋勯犲嚱鏁版彁渚涚粰浣犮
銆銆class TestClass
銆銆{
銆銆public TestClass(): base() {} // 鐢盋LR鎻愪緵
銆銆}
銆銆涓嬮潰鍒椾婦浜嗗嚑縐嶇被鍨嬬殑鏋勯犲嚱鏁
銆銆1錛夌己鐪佹瀯閫犲嚱鏁
銆銆class TestClass
銆銆{
銆銆public TestClass(): base() {}
銆銆}
銆銆涓婇潰宸蹭粙緇嶏紝瀹冪敱緋葷粺錛圕LR錛夋彁渚涖
銆銆2錛夊疄渚嬫瀯閫犲嚱鏁
銆銆瀹炰緥鏋勯犲嚱鏁版槸瀹炵幇瀵圭被涓瀹炰緥榪涜屽垵濮嬪寲鐨勬柟娉曟垚鍛樸傚傦細
銆銆using System;
銆銆class Point
銆銆{
銆銆public double x, y;
銆銆public Point()
銆銆{
銆銆this.x = 0;
銆銆this.y = 0;
銆銆}
銆銆public Point(double x, double y)
銆銆{
銆銆this.x = x;
銆銆this.y = y;
銆銆}
銆銆}
銆銆class Test
銆銆{
銆銆static void Main()
銆銆{
銆銆Point a = new Point();
銆銆Point b = new Point(3, 4); // 鐢ㄦ瀯閫犲嚱鏁板垵濮嬪寲瀵硅薄
銆銆}
銆銆}
銆銆澹版槑浜嗕竴涓綾籔oint錛屽畠鎻愪緵浜嗕袱涓鏋勯犲嚱鏁般傚畠浠鏄閲嶈澆鐨勩備竴涓鏄娌℃湁鍙傛暟鐨凱oint鏋勯犲嚱鏁板拰涓涓鏄鏈変袱涓猟ouble鍙傛暟鐨凱oint鏋勯犲嚱鏁般傚傛灉綾諱腑娌℃湁鎻愪緵榪欎簺鏋勯犲嚱鏁幫紝閭d箞浼欳LR浼氳嚜鍔ㄦ彁渚涗竴涓緙虹渷鏋勯犲嚱鏁扮殑銆備絾涓鏃︾被涓鎻愪緵浜嗚嚜瀹氫箟鐨勬瀯閫犲嚱鏁幫紝濡侾oint()鍜孭oint(double x, double y)錛屽垯緙虹渷鏋勯犲嚱鏁板皢涓嶄細琚鎻愪緵錛岃繖涓鐐硅佹敞鎰忋
銆銆3錛 闈欐佹瀯閫犲嚱鏁
銆銆闈欐佹瀯閫犲嚱鏁版槸瀹炵幇瀵逛竴涓綾昏繘琛屽垵濮嬪寲鐨勬柟娉曟垚鍛樸傚畠涓鑸鐢ㄤ簬瀵歸潤鎬佹暟鎹鐨勫垵濮嬪寲銆傞潤鎬佹瀯閫犲嚱鏁頒笉鑳芥湁鍙傛暟錛屼笉鑳芥湁淇楗扮﹁屼笖涓嶈兘琚璋冪敤錛屽綋綾昏鍔犺澆鏃訛紝綾葷殑闈欐佹瀯閫犲嚱鏁拌嚜鍔ㄨ璋冪敤銆傚傦細
銆銆using System.Data;
銆銆class Employee
銆銆{
銆銆private static DataSet ds;
銆銆static Employee()
銆銆{
銆銆ds = new DataSet(...);
銆銆}
銆銆}
銆銆澹版槑浜嗕竴涓鏈夐潤鎬佹瀯閫犲嚱鏁扮殑綾籈mployee銆傛敞鎰忛潤鎬佹瀯閫犲嚱鏁板彧鑳藉歸潤鎬佹暟鎹鎴愬憳榪涜屽垵濮嬪寲錛岃屼笉鑳藉歸潪闈欐佹暟鎹鎴愬憳榪涜屽垵濮嬪寲銆備絾鏄錛岄潪闈欐佹瀯閫犲嚱鏁版棦鍙浠ュ歸潤鎬佹暟鎹鎴愬憳璧嬪礆紝涔熷彲浠ュ歸潪闈欐佹暟鎹鎴愬憳榪涜屽垵濮嬪寲銆
銆銆濡傛灉綾諱粎鍖呭惈闈欐佹垚鍛橈紝浣犲彲浠ュ壋寤轟竴涓猵rivate鐨勬瀯閫犲嚱鏁幫細private TestClass() {鈥}錛屼絾鏄痯rivate鎰忓懗鐫浠庣被鐨勫栭潰涓嶅彲鑳借塊棶璇ユ瀯閫犲嚱鏁般傛墍浠ワ紝瀹冧笉鑳借璋冪敤錛屼笖娌℃湁瀵硅薄鍙浠ヨ璇ョ被瀹氫箟瀹炰緥鍖栥
銆銆浠ヤ笂鏄鍑犵嶇被鍨嬫瀯閫犲嚱鏁扮殑綆鍗曡繍鐢錛屼笅闈㈠皢閲嶇偣浠嬬粛涓涓嬪湪綾葷殑灞傛$粨鏋勪腑錛堝嵆緇ф壙緇撴瀯涓錛夊熀綾誨拰媧劇敓綾葷殑鏋勯犲嚱鏁扮殑浣跨敤鏂瑰紡銆傛淳鐢熺被瀵硅薄鐨勫垵濮嬪寲鐢卞熀綾誨拰媧劇敓綾誨叡鍚屽畬鎴愶細鍩虹被鐨勬垚鍛樼敱鍩虹被鐨勬瀯閫犲嚱鏁板垵濮嬪寲錛屾淳鐢熺被鐨勬垚鍛樼敱媧劇敓綾葷殑鏋勯犲嚱鏁板垵濮嬪寲銆
銆銆褰撳壋寤烘淳鐢熺被鐨勫硅薄鏃訛紝緋葷粺灝嗕細璋冪敤鍩虹被鐨勬瀯閫犲嚱鏁板拰媧劇敓綾葷殑鏋勯犲嚱鏁幫紝鏋 閫犲嚱鏁扮殑鎵ц屾″簭鏄錛氬厛鎵ц屽熀綾葷殑鏋勯犲嚱鏁幫紝鍐嶆墽琛屾淳鐢熺被鐨勬瀯閫犲嚱鏁般傚傛灉媧劇敓綾誨張鏈夊硅薄鎴愬憳錛屽垯錛屽厛鎵ц屽熀綾葷殑鏋勯犲嚱鏁幫紝鍐嶆墽琛屾垚鍛樺硅薄綾葷殑鏋勯犲嚱鏁幫紝鏈鍚庢墽琛屾淳鐢熺被鐨勬瀯閫犲嚱鏁般
銆銆鑷充簬鎵ц屽熀綾葷殑浠涔堟瀯閫犲嚱鏁幫紝緙虹渷鎯呭喌涓嬫槸鎵ц屽熀綾葷殑鏃犲弬鏋勯犲嚱鏁幫紝濡傛灉瑕佹墽琛屽熀綾葷殑鏈夊弬鏋勯犲嚱鏁幫紝鍒欏繀欏誨湪媧劇敓綾繪瀯閫犲嚱鏁扮殑鎴愬憳鍒濆嬪寲琛ㄤ腑鎸囧嚭銆傚傦細
銆銆class A
銆銆{ private int x;
銆銆public A( ) { x = 0; }
銆銆public A( int i ) { x = i; }
銆銆};
銆銆class B : A
銆銆{ private int y;
銆銆public B( ) { y = 0; }
銆銆public B( int i ) { y = i; }
銆銆public B( int i, int j ):A(i) { y = j; }
銆銆};
銆銆B b1 = new B(); //鎵ц屽熀綾籄鐨勬瀯閫犲嚱鏁癆()錛屽啀鎵ц屾淳鐢熺被鐨勬瀯閫犲嚱鏁癇()
銆銆B b2 = new B(1); //鎵ц屽熀綾籄鐨勬瀯閫犲嚱鏁癆()錛屽啀鎵ц屾淳鐢熺被鐨勬瀯閫犲嚱鏁癇(int)
銆銆B b3 = new B(0,1); //鎵ц屾墽琛屽熀綾籄鐨勬瀯閫犲嚱鏁癆(int) 錛屽啀鎵ц屾淳鐢熺被鐨
銆銆鏋勯犲嚱鏁癇(int,int)
銆銆鍦ㄨ繖閲屾瀯閫犲嚱鏁扮殑鎵ц屾″簭鏄涓瀹氳佸垎鏋愭竻妤氱殑銆傚彟澶栵紝濡傛灉鍩虹被A涓娌℃湁鎻愪緵鏃犲弬鏋勯犲嚱鏁皃ublic A( ) { x = 0; }錛屽垯鍦ㄦ淳鐢熺被鐨勬墍鏈夋瀯閫犲嚱鏁版垚鍛樺垵濮嬪寲琛ㄤ腑蹇呴』鎸囧嚭鍩虹被A鐨勬湁鍙傛瀯閫犲嚱鏁癆(i)錛屽備笅鎵紺猴細
銆銆class A
銆銆{ private int x;
銆銆public A( int i ) { x = i; }
銆銆};
銆銆class B : A
銆銆{ private int y;
銆銆public B():A(i) { y = 0; }
銆銆public B(int i):A(i) { y = i; }
銆銆public B(int i, int j):A(i) { y = j; }
銆銆};
銆銆 涓夛紟鏋愭瀯鍑芥暟鍜屽瀮鍦懼洖鏀跺櫒鍦–#涓鐨勮繍鐢
銆銆鏋愭瀯鍑芥暟鏄瀹炵幇閿姣佷竴涓綾葷殑瀹炰緥鐨勬柟娉曟垚鍛樸傛瀽鏋勫嚱鏁頒笉鑳芥湁鍙傛暟錛屼笉鑳戒換浣曚慨楗扮﹁屼笖涓嶈兘琚璋冪敤銆傜敱浜庢瀽鏋勫嚱鏁扮殑鐩鐨勪笌鏋勯犲嚱鏁扮殑鐩稿弽錛屽氨鍔犲墠緙鈥榽鈥欎互紺哄尯鍒銆
銆銆鉶界劧C#錛堟洿紜鍒囩殑璇存槸CLR錛夋彁渚涗簡涓縐嶆柊鐨勫唴瀛樼$悊鏈哄埗---鑷鍔ㄥ唴瀛樼$悊鏈哄埗錛圓utomatic memory management錛夛紝璧勬簮鐨勯噴鏀炬槸鍙浠ラ氳繃鈥滃瀮鍦懼洖鏀跺櫒鈥 鑷鍔ㄥ畬鎴愮殑錛屼竴鑸涓嶉渶瑕佺敤鎴峰共棰勶紝浣嗗湪鏈変簺鐗規畩鎯呭喌涓嬭繕鏄闇瑕佺敤鍒版瀽鏋勫嚱鏁扮殑錛屽傚湪C#涓闈炴墭綆¤祫婧愮殑閲婃斁銆
銆銆璧勬簮鐨.閲婃斁涓鑸鏄閫氳繃"鍨冨溇鍥炴敹鍣"鑷鍔ㄥ畬鎴愮殑,浣嗗叿浣撴潵璇,浠嶆湁浜涢渶瑕佹敞鎰忕殑鍦版柟錛
銆銆1. 鍊肩被鍨嬪拰寮曠敤綾誨瀷鐨勫紩鐢ㄥ叾瀹炴槸涓嶉渶瑕佷粈涔"鍨冨溇鍥炴敹鍣"鏉ラ噴鏀懼唴瀛樼殑,鍥犱負褰撳畠浠鍑轟簡浣滅敤鍩熷悗浼氳嚜鍔ㄩ噴鏀炬墍鍗犲唴瀛橈紝鍥犱負瀹冧滑閮戒繚瀛樺湪鏍(Stack)涓;
銆銆2. 鍙鏈夊紩鐢ㄧ被鍨嬬殑寮曠敤鎵鎸囧悜鐨勫硅薄瀹炰緥鎵嶄繚瀛樺湪鍫(Heap)涓,鑰屽爢鍥犱負鏄涓涓鑷鐢卞瓨鍌ㄧ┖闂,鎵浠ュ畠騫舵病鏈夊儚"鏍"閭f牱鏈夌敓瀛樻湡("鏍"鐨勫厓緔犲脊鍑哄悗灝變唬琛ㄧ敓瀛樻湡緇撴潫,涔熷氨浠h〃閲婃斁浜嗗唴瀛),騫朵笖瑕佹敞鎰忕殑鏄,"鍨冨溇鍥炴敹鍣"鍙瀵硅繖鍧楀尯鍩熻搗浣滅敤;
銆銆鐒惰,鏈変簺鎯呭喌涓嬶紝褰撻渶瑕侀噴鏀鵑潪鎵樼¤祫婧愭椂,灝卞繀欏婚氳繃鍐欎唬鐮佺殑鏂瑰紡鏉ヨВ鍐熾傞氬父鏄浣跨敤鏋愭瀯鍑芥暟閲婃斁闈炴墭綆¤祫婧愶紝灝嗙敤鎴瘋嚜宸辯紪鍐欑殑閲婃斁闈炴墭綆¤祫婧愮殑浠g爜孌墊斁鍦ㄦ瀽鏋勫嚱鏁頒腑鍗沖彲銆傞渶瑕佹敞鎰忕殑鏄,濡傛灉涓涓綾諱腑娌℃湁浣跨敤鍒伴潪鎵樼¤祫婧,閭d箞涓瀹氫笉瑕佸畾涔夋瀽鏋勫嚱鏁,榪欐槸鍥犱負瀵硅薄鎵ц屼簡鏋愭瀯鍑芥暟,閭d箞"鍨冨溇鍥炴敹鍣"鍦ㄩ噴鏀炬墭綆¤祫婧愪箣鍓嶈佸厛璋冪敤鏋愭瀯鍑芥暟錛岀劧鍚庣浜屾℃墠鐪熸i噴鏀炬墭綆¤祫婧愶紝榪欐牱涓鏉ワ紝涓ゆ″垹闄ゅ姩浣滅殑鑺遍攢姣斾竴嬈″ぇ澶氱殑銆備笅闈浣跨敤涓孌典唬鐮佹潵紺烘瀽鏋勫嚱鏁版槸濡備綍浣跨敤鐨勶細
銆銆public class ResourceHolder
銆銆{
銆銆~ResourceHolder()
銆銆{
銆銆// 榪欓噷鏄娓呯悊闈炴墭綆¤祫婧愮殑鐢ㄦ埛浠g爜孌
銆銆}
銆銆}
銆銆 鍥涳紟灝忕粨
銆銆鏋勯犲嚱鏁頒笌鏋愭瀯鍑芥暟鉶界劧鏄涓涓綾諱腑褰㈠紡涓婅緝綆鍗曠殑鍑芥暟錛屼絾瀹冧滑鐨勪嬌鐢ㄥ喅闈炵湅涓婂幓閭d箞綆鍗曪紝鍥犳ょ伒媧昏屾g『鐨勪嬌鐢ㄦ瀯閫犲嚱鏁頒笌鏋愭瀯鍑芥暟鑳藉熷府浣犳洿濂界殑鐞嗚ВCLR鐨勫唴瀛樼$悊鏈哄埗錛屼互鍙婃洿濂界殑綆$悊緋葷粺涓鐨勮祫婧愩
❸ 構造函數的調用順序
構造代碼塊的作用同樣是給對象進行初始化。對象一建立就運行構造代碼塊了,而且優先於構造函數執行。這里要強調一下,有對象建立,才會運行構造代碼塊,類不能調用構造代碼塊的,而且構造代碼塊與構造函數的執行順序是前者先於後者執行。
構造代碼塊與構造函數的區別是:構造代碼塊是給所有對象進行統一初始化,而構造函數是給對應的對象初始化,因為構造函數是可以多個的,運行哪個構造函數就會建立什麼樣的對象,但無論建立哪個對象,都會先執行相同的構造代碼塊。也就是說,構造代碼塊中定義的是不同對象共性的初始化內容。
1)使用new操作符創建對象。如果含有靜態成員變數:
靜態成員變數的靜態代碼塊 -> 靜態成員變數的代碼塊 -> 靜態成員變數的構造方法) -> 靜態代碼塊 -> 代碼塊 -> 構造函數
2)如果不含靜態成員變數:
靜態代碼塊 -> (靜態成員變數的靜態代碼塊 -> 靜態成員變數的代碼塊 -> 靜態成員變數的構造方法) -> 代碼塊 -> 構造函數。靜態代碼塊只執行一次,而每次創建對象都會調用共同的構造代碼塊,而構造函數也只在創建對象時執行該對象的構造函數。