C 學習筆記 結構與類

2021-07-01 22:38:27 字數 3801 閱讀 4736

在c#中有大量的值型別, int,char,float…等c#的預定義的基本型別都是值型別,這裡面string是乙個例外。值型別直接包含值,變數引用的位置就是值在記憶體中實際儲存的位置,儲存在稱為棧的記憶體區域內。引用型別和引用它們的變數指向資料儲存位置。引用型別並不直接儲存值,它們儲存的是對乙個記憶體位置的引用(記憶體位址),要去那個位置才能找到真正的資料。引用型別指向的記憶體區域稱為堆。

我們需要使用自定義的型別時,自定義的引用型別很常用,就是我們常用的「類」。在這裡要提一下自定義的值型別,一種是「結構」,另外一種是「列舉」。•    c++中的結構是多餘的東西,僅僅為了相容c而存在。c#中的結構與類有許多實質的區別,結構是輕量級的自定義資料型別,其資料儲存於棧中。

比較專案

struct

class

1.         儲存位置

棧託管堆

2.         變數賦值為null

不能可以

3.         繼承與派生

不支援支援

4.         定義無參建構函式不能能

5.         建構函式初始化所有字段

必須不必

6.         用new來例項化乙個物件

不一定必須

7.         定義析構函式不能能

8.         物件複製

正本與副本無關

淺拷貝和深拷貝

9.         如何**

無需**

自動**機制

10.     引數傳送

按值傳送

按位址傳送

11.     使用初始化表

不能可以

12.     作為list元素能否修改

不能可以

c++中,結構和類幾乎是同義詞,區別只在於:結構的成員預設為公開的,類的成員預設為私有的。但是在c#中,結構和類的成員預設都是私有的。

下面用乙個**例項說明一下上述區別的表現,**選自《c#本質論4.0》,**清單8-1:

using system;

using system.diagnostics;

using system.componentmodel;

using system.text;

using system.collections.generic;

namespace myprocesssample

//error

//5. 建構函式初始化所有字段,如下面的初始化必須包括全部三個字段

public angle(int hours, int minutes, int seconds)

public int hours

}public int _hours;

public int minutes

}private int _minutes;

public int seconds

}private int _seconds;

public angle move(int hours, int minutes, int seconds)

}// declaring a class - a reference type

// (declaring it as a struct would create a value type

// larger than 16 bytes.)

class coordinate

public angle longitude

set

}private angle _longitude;

public angle latitude

set

}private angle _latitude;

}class myprocess

;angle ag4 = new angle ;//這裡說明struct也是可以使用初始化列表的,前提是這個欄位是公有的

angle ag5 = new angle(7, 3, 1);

angle ag6 = new angle(9, 9, 9);

listallags = new list() ;

console.writeline(allags[0].hours + "," + allags[1].hours + "," + allags[2].hours);

allags[0] = allags[1];

console.writeline(allags[0].hours + "," + allags[1].hours + "," + allags[2].hours);

allags[0] = ag5;

console.writeline(allags[0].hours + "," + allags[1].hours + "," + allags[2].hours);

coordinate cd5 = new coordinate ;

listallcds = new list() ;

console.writeline(allcds[0].latitude.minutes + "," + allcds[1].latitude.minutes);

allcds[0] = allcds[1];

console.writeline(allcds[0].latitude.minutes + "," + allcds[1].latitude.minutes);

allcds[0] = cd5;

console.writeline(allcds[0].latitude.minutes + "," + allcds[1].latitude.minutes);

//以下說明引用型別的賦值存在深拷貝,淺拷貝的問題,直接賦值相當於淺拷貝

coordinate cd6 = cd5;

console.writeline(cd6.longitude.hours + "," + cd5.longitude.hours);

cd6.longitude = new angle(999, 999, 999);

console.writeline(cd6.longitude.hours + "," + cd5.longitude.hours);}}

}

對第8條,物件的複製方式,struct的形式完全和常用值型別一樣,但是class的複製就涉及到深拷貝和淺拷貝,可具體參考本站其它博文(

第11條,第12條來自陳老師的講課資料,不過現在驗證來好象有點出入,比如第11條,如果struct裡有乙個公有的字段,那麼是可以使用初始化列表初始化的。第12條也是,當時陳老師是這麼講解的:

list中,元素只能用索引器來獲取,例如 a[i]。索引器返回的本是可讀可寫的元素,但struct元素是按值傳送的,修改返回值對於list中的元素毫無影響。例如,a[i] = a[j];     c#此時發出編譯錯誤,實在是提醒程式設計師別誤入陷阱。但元素如果是class的,返回值則是按位址傳送的,是乙個引用,修改其值就是修改list中的元素, a[i] = a[j];  是允許的。

經過驗證,見上述**的第109-122行,這些都是可以實現的。或者我對這一段理解有問題,還有待於深入的**。

struct 型別適於表示 point、rectangle 和 color 等輕量物件。 儘管使用自動實現的屬性將乙個點表示為類同樣方便,但在某些情況下使用結構更加有效。 例如,如果宣告乙個 1000 個 point 物件組成的陣列,為了引用每個物件,則需分配更多記憶體;這種情況下,使用結構可以節約資源。 因為 .net framework 包含乙個名為 point 的物件,所以本示例中的結構命名為「coords」。

public struct coords

}

將較小的類宣告為結構,可以提高系統的處理效率。

C 學習筆記03 類與物件

公有 私有 保護成員 在關鍵字public後面宣告,它們是類與外部的介面,任何外部函式都可以訪問公有型別資料和函式 在關鍵字private後面宣告,只允許本類中的函式訪問,而類外部的任何函式都不能訪問 在關鍵字protected後面宣告,與private類似,其差別表現在繼承與派生時對派生類的影響不...

C 學習筆記16 結構體和類

結構體和類的區別 在做乙個專案時,使用了較多的結構體,並且存在一些結構體的巢狀,即某結構體成員集合包含另乙個結構體等,總是出現一些奇怪的錯誤,才終於下決心好好分析一下到底類和結構體有啥不同,雖然它們很相似,但確實有很大的不同,用不好難免出的問題會比較多,現總結一下 一 結構體和類非常相似 1,定義和...

c 學習筆記(四) 類和結構

類的預設訪問許可權是private 結構是public 該關鍵字修飾的變數可以在類的const方法中修改 class node 建議使用如下方式 正確 constref constref int ii i ii ci ii ri ii 錯誤 constref constref int ii 原因 效...