C 中一些易混淆概念總結(五)

2022-09-23 19:42:10 字數 2951 閱讀 7085

這次主要分享的內容是關於繼承的知識。

首先,我們先來看看繼承;

既然有繼承,就要有父類和子類,來看下面的一段**:

複製**

class person

public void run()

}  class student : person

複製**  

然後我在main()函式中例項化子類的物件,**如下:

static void main(string args)

那麼在這個過程中記憶體中發生了些什麼呢?

我們先來看misl的中間**,看看那能發現些什麼  

由此我們可以發現子類繼承了父類的所有成員包括private和protect,並為這些成員開闢了空間來儲存。

我們再來例項化我們的子類,然後訪問父類的字段和方法,會發現,如下的現象  

所以雖然子類為父類的所有成員在堆中都開闢了空間,但是私有成員(private)和受保護的成員(protected)訪問不到。  

所以在記憶體中的情況如下圖:  

看下面的**,我們來**一下在子類中this關鍵字和base關鍵字所訪問的類的成員有哪些,**如下:

複製**

class student : person

年紀,來自", cla, adre);

}public void sing()

}複製**

所以在子類中this關鍵字和base關鍵字的訪問範圍的示意圖如下:  

二,關於子類物件的建構函式和父類建構函式的執行順序

我們分別為父類和子類新增顯式的建構函式,**如下

複製**

class person

public void hello()

public void run()

}class student : person

}複製**

我們使用vs的單步除錯,來看父類和子類顯式建構函式的執行順序,如下圖(動態,可以看到過程):  

很容易的可以發現,當建立子類物件的時候

①先呼叫了子類的建構函式

②呼叫了父類的建構函式

③執行了父類的建構函式

④執行了子類的建構函式  

那麼為什麼會這樣呢?

我嘗試通過反編譯看原始碼來解釋這個原因,但是反編譯的結果如下,  

沒有發現有什麼特別的地方可以解釋這個原因。  

最後還是查閱微軟的msdn官方文件找到了答案(原文位址點選這裡)  

根據微軟官方的**示例,那麼下面的**的效果也是相同的

複製**

//子類的建構函式

public student ()

//這裡的**和上面的**效果是相同的

public student()

:base()

複製**  

也就是說只要在子類顯式的宣告了無參的建構函式,在例項化子類的物件是,子類的無參建構函式都會去呼叫父類無參的建構函式。

那麼,如果父類沒有這個無參的建構函式則會報錯。

如下面的**:

複製**

class person

//父類的有引數的建構函式,這裡覆蓋了無參的建構函式

public person (string str)

",str);

}public void hello()

public void run()

}class student : person

public student(string strname)

",strname);}}

複製**

這時候編譯會報錯,  

因為在父類中有引數的建構函式覆蓋了無引數的建構函式,所以在子類的無引數的建構函式沒辦法**父類的無引數的建構函式初始化父類的成員變數。所以報錯。  

那麼在初始化子類的時候,為什麼要呼叫父類的建構函式呢?

在初始化子類之前需要通過建構函式初始化父類的成員變數

父類的建構函式先於子類的建構函式執行的意義是什麼呢?

當在父類的建構函式中和子類的建構函式中為父類的非私有成員變數賦不同預設值。當例項化子類,子類要呼叫建構函式初始化成員變數,如果先執行了子類的建構函式,再執行父類的建構函式,父類成員欄位的值會覆蓋子類成員欄位的值。但是我們想得到的是子類的屬性值。所以為了解決資料衝突,父類的建構函式要先於子類的建構函式執行。

如下面的**:

複製**

class person

", streatetype);}}

class student : person

",streatetype);}}

複製**

這時候我們通過,宣告子類物件訪問streatetype的值,如下:

student stu1 = new student();

//stu1.

string str = stu1.streatetype.tostring();

console.writeline(str);

console.readkey();

這裡肯定是要列印出子類的屬性streatetype的值,如果先執行子類建構函式對streatetype賦值,然後父類的建構函式賦值覆蓋streatetype的初始值。那麼列印出的將是父類成員欄位的值。所以,父類的建構函式先於子類的建構函式執行。

列印結果如下:  

三,子類是否可以有和父類的同名方法

看下面的**,我們宣告乙個父類person:  

複製**

class person

", streatetype);

}public person(string str)

", str);

}public void hello()

public void run()

}複製**  

宣告乙個子類繼承person,**如下:

複製**

class worker:person

public new void  run()

}

C 中一些容易混淆的概念

指標函式 是指帶指標的函式,本身是函式,只是返回值是某乙個型別的指標。int fun int x 函式指標 指向函式的指標變數,即本質是乙個指標變數。int fun int x void fun 定義函式指標 void test int main void test typedef typedef ...

C 中一些常見函式總結

一般形式 strcmp 字串1,字串2 功能 比較兩個字串的大小 比較方式 兩個字串自左向右逐個字元相比 按ascii值大小相比較 直到遇到不同的字元或遇 0 為止。1 字串1 字串2 返回0 2 字串1 字串2 返回乙個正整數 不是1 3 字串1 字串2 返回乙個負整數 不是 1 特別注意 str...

Web前端易混淆的一些知識

相同點 都用於瀏覽器端儲存的快取資料 不同點 儲存內容是否傳送到伺服器端 當設定了cookie後,資料會傳送到伺服器端,造成一定的寬頻浪費 storage則會將資料儲存 到本地,不會造成寬頻浪費 資料儲存大小不同 cookie資料不能超過4k,適用於會話標識 storage資料儲存可以達到5m 資料...