public與 private的區別

 

雖然兩者都可以捆綁行爲。  

  但是,理解不一樣。  

  struct,就是對程序員全局可見的數據與方法。簡化數據邏輯結構的設計。可以說是一種自定義的數據結構。  

  而class,則是將數據與方法封裝,即讓行爲與數據一致。則是一種編程方法。即客觀世界在代碼世界中的體現。體現的是一種編程思想。

首先,討論這個問題應該僅從語法上討論,如果討論不同人之間編程風格上的差異,那這個問題是沒有答案的。畢竟不同的人偏好不同。

從語法上,在C++中(只討論C++中)。class和struct做類型定義時只有兩點區別:

(一)默認繼承權限。如果不明確指定,來自class的繼承按照private繼承處理,來自struct的繼承按照public繼承處理;

(二)成員的默認訪問權限。class的成員默認是private權限,struct默認是public權限。

除了這兩點,class和struct基本就是一個東西。語法上沒有任何其它區別。

不能因爲學過C就總覺得連C++中struct和class都區別很大,下面列舉的說明可能比較無聊,因爲struct和class本來就是基本一樣的東西,無需多說。但這些說明可能有助於澄清一些常見的關於struct和class的錯誤認識:

(1)都可以有成員函數;包括各類構造函數,析構函數,重載的運算符,友元類,友元結構,友元函數,虛函數,純虛函數,靜態函數;

(2)都可以有一大堆public/private/protected修飾符在裏邊;

(3)雖然這種風格不再被提倡,但語法上二者都可以使用大括號的方式初始化:A a = {1, 2, 3};不管A是個struct還是個class,前提是這個類/結構足夠簡單,比如所有的成員都是public的,所有的成員都是簡單類型,沒有顯式聲明的構造函數。

(4)都可以進行復雜的繼承甚至多重繼承,一個struct可以繼承自一個class,反之亦可;一個struct可以同時繼承5個class和5個struct,雖然這樣做不太好。

(5)如果說class的設計需要注意OO的原則和風格,那麼沒任何理由說設計struct就不需要注意。

(6)再次說明,以上所有說法都是指在C++語言中,至於在C裏的情況,C裏是根本沒有“class”,而C的struct從根本上也只是個包裝數據的語法機制。

---------------------------------------------------------------

最後,作爲語言的兩個關鍵字,除去定義類型時有上述區別之外,另外還有一點點:“class”這個關鍵字還用於定義模板參數,就像“typename”。但關鍵字“struct”不用於定義模板參數。

(個人認爲最後一段是毫無意義的,因爲C++中用來定義模板參數的“class”關鍵字並非代表“類”。olivue_antil)

----------------------------------------------

如果沒有多態和虛擬繼承,在C++中,struct和class的存取效率完全相同!簡單的說就是,存取class的data member和非virtual function效率和struct完全相同!不管該data member是定義在基類還是派生類的。

如果不是爲了和C兼容,C++中就不會有struct關鍵字。因此建議是:如果不需要與C兼容或傳遞參數給C程序,不要在C++中用struct。

注意class的data member在內存中的佈局可不一定是data member的申明次序。C++只保證處於同一個access section的data member按照申明次序排列。

-- 《Inside The C++ Object Model》

 

 

因爲C++要兼容C,C++中的struct是從C中繼承過來的。

C中的struct可以用來定義一種數據類型,但C是一種面向過程的語言,沒有面向對象的思想,那麼struct在C語言中自然沒有面向對象的概念。它僅僅能定義一種類型。

最初學習C++的時候覺得struct和C中的是一樣的,但後來發現struct也可以定義成員函數,研究以後發現:C++中的struct還可以:繼承,實現多態。

但是你如果簡單的認爲struct和class是完全一樣的就錯了,在網上經過查找發現,它們還是有細微差別的:

1)默認的繼承訪問權限。struct是public的,class是private的。

如果不知道什麼是public繼承,什麼是private繼承的,可以去查書,這裏暫不討論。

你可以寫如下的代碼:

struct A

{

char a;

};

struct B : A

{

char b;

};

這個時候B是public繼承A的。如果都將上面的struct改成class,那麼B是private繼承A的。這就是默認的繼承訪問權限。所以我們在平時寫類繼承的時候,通常會這樣寫:

struct B : public A

就是爲了指明是public繼承,而不是用默認的private繼承。

當然,到底默認是public繼承還是private繼承,取決於子類而不是基類。我的意思是,struct可以繼承class,同樣class也可以繼承struct,那麼默認的繼承訪問權限是看子類到底是用的struct還是class。如下:

struct A{};

class B : A{}; //private繼承

struct C : B{}; //public繼承

2)struct作爲數據結構的實現體,它默認的數據訪問控制是public的,而class作爲對象的實現體,它默認的成員變量訪問控制是private的。

注意我上面的用詞,我依舊強調struct是一種數據結構的實現體,雖然它是可以像class一樣的用。我依舊將struct裏的變量叫數據,class內的變量叫成員,雖然它們並無區別。其實,到底是用struct還是class,完全看個人的喜好,你可以將你程序裏所有的class全部替換成struct,它依舊可以很正常的運行。但我給出的最好建議,還是:當你覺得你要做的更像是一種數據結構的話,那麼用struct,如果你要做的更像是一種對象的話,那麼用class。

當然,我在這裏還要強調一點的就是,對於訪問控制,應該在程序裏明確的指出,而不是依靠默認,這是一個良好的習慣,也讓你的代碼更具可讀性。

說到這裏,很多瞭解的人或許都認爲這個話題可以結束了,因爲他們知道struct和class的“唯一”區別就是訪問控制。很多文獻上也確實只提到這一個區別。

但我上面卻沒有用“唯一”,而是說的“最本質”,那是因爲,它們確實還有另一個區別,雖然那個區別我們平時可能很少涉及。那就是:“class”這個關鍵字還用於定義模板參數,就像“typename”。但關鍵字“struct”不用於定義模板參數。這一點在Stanley B.Lippman寫的Inside the C++ Object Model有過說明。

問題討論到這裏,基本上應該可以結束了。但有人曾說過,他還發現過其他的“區別”,那麼,讓我們來看看,這到底是不是又一個區別。

還是上面所說的,C++中的struct是對C中的struct的擴充,既然是擴充,那麼它就要兼容過去C中struct應有的所有特性。例如你可以這樣寫:

struct A //定義一個struct

{

char c1;

int n2;

double db3;

};

A a={'p',7,3.1415926}; //定義時直接賦值

也就是說struct可以在定義的時候用{}賦初值。那麼問題來了,class行不行呢?將上面的struct改成class,試試看。報錯!噢~於是那人跳出來說,他又找到了一個區別。我們仔細看看,這真的又是一個區別嗎?

你試着向上面的struct中加入一個構造函數(或虛函數),你會發現什麼?對,struct也不能用{}賦初值了。的確,以{}的方式來賦初值,只是用一個初始化列表來對數據進行按順序的初始化,如上面如果寫成A a={'p',7};則c1,n2被初始化,而db3沒有。這樣簡單的copy操作,只能發生在簡單的數據結構上,而不應該放在對象上。加入一個構造函數或是一個虛函數會使struct更體現出一種對象的特性,而使此{}操作不再有效。事實上,是因爲加入這樣的函數,使得類的內部結構發生了變化。而加入一個普通的成員函數呢?你會發現{}依舊可用。其實你可以將普通的函數理解成對數據結構的一種算法,這並不打破它數據結構的特性。

那麼,看到這裏,我們發現即使是struct想用{}來賦初值,它也必須滿足很多的約束條件,這些條件實際上就是讓struct更體現出一種數據機構而不是類的特性。那爲什麼我們在上面僅僅將struct改成class,{}就不能用了呢?其實問題恰巧是我們之前所講的——訪問控制!你看看,我們忘記了什麼?對,將struct改成class的時候,訪問控制由public變爲private了,那當然就不能用{}來賦初值了。加上一個public,你會發現,class也是能用{}的,和struct毫無區別!!!

 

 

區別有三: 

  1:   類可以繼承,結構不可以. 

  2:   類是引用類型,結構是值類型 

  3:   類在堆中,結構在棧分配內存

 

1.值類型與引用類型

  結構是值類型:值類型在堆棧上分配地址,所有的基類型都是結構類型,例如:int 對應System.int32 結構,string 對應 system.string 結構 ,通過使用結構可以創建更多的值類型

  類是引用類型:引用類型在堆上分配地址

  堆棧的執行效率要比堆的執行效率高,可是堆棧的資源有限,不適合處理大的邏輯複雜的對象。所以結構處理作爲基類型對待的小對象,而類處理某個商業邏輯

  因爲結構是值類型所以結構之間的賦值可以創建新的結構,而類是引用類型,類之間的賦值只是複製引用

 

 2.繼承性

  結構:不能從另外一個結構或者類繼承,本身也不能被繼承,雖然結構沒有明確的用sealed聲明,可是結構是隱式的sealed .

  類:完全可擴展的,除非顯示的聲明sealed 否則類可以繼承其他類和接口,自身也能被繼承

3.內部結構:

  結構:

  沒有默認的構造函數,但是可以添加構造函數

  沒有析構函數

  沒有 abstract 和 sealed(因爲不能繼承)

  不能有protected 修飾符

  可以不使用new 初始化

  在結構中初始化實例字段是錯誤的

  類:

  有默認的構造函數

  有析構函數

  可以使用 abstract 和 sealed

  有protected 修飾符

  必須使用new 初始化

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章