//=====================================================================
//TITLE:
// C++ VS C#(8):類定義
//AUTHOR:
// norains
//DATE:
// Thursday 17-January-2011
//Environment:
// Visual Studio 2010
// Visual Studio 2005
//=====================================================================
1. 類定義
C++和C#都具備物件導向的特性,自然而然,兩者都有類這個玩意。無論是C++,或是C#,定義類的關鍵字都是class。也就是說,這兩種語言都可以這樣聲明一個類:
class CMyClass<br /> {<br /> //Class members<br /> };
至此,C++的聲明就是如此了。但C#還在此基礎上再度發展,在class之前還有internal和public兩個關鍵字可選。預設的情況下,類聲明是內部的,只有當前項目的代碼才能訪問它,換句話來說,上面的聲明在C#中相當於如此:
internal class CMyClass<br /> {<br /> //Class members<br /> };
如果想在別的項目中也能使用該代碼,那麼必須用public來進行修飾,如:
public class CMyClass<br /> {<br /> //Class members<br /> };
除了這兩個訪問修飾以外,還能指定類是否是抽象的,或密封的。抽象的關鍵字是abstract,表明其不能執行個體化,只能繼承;密封的關鍵字是sealed,表示其不能被繼承。從意思上我們就可以知道,這兩個關鍵字是互斥的,兩者只能選擇其一。
如果我們聲明一個抽象的公用類,代碼可以書寫如下:
public abstract class CmyClass<br /> {<br /> //Class members<br /> }
public和abstract這兩個關鍵字的次序無關緊要,可以隨意顛倒。
我們來討論一個很有意思的問題,C++沒有這兩個關鍵字,是不是就沒辦法實作類別似於C#的功能了呢?答案當然不是了。我們來看看,如何用C++來實現C#的這兩個特性。
首先來看的是密封,也就是不能讓這個類被繼承。雖然C++沒有sealed關鍵字,但實現這個功能一點也不費功夫,我們只要將建構函式或解構函式聲明為private即可,如下代碼所示:
//父類<br /> class CMyBase<br /> {<br /> //將建構函式和解構函式聲明為private<br /> private:<br /> CMyBase(){};<br /> virtual ~CMyBase(){};<br /> };</p><p> //子類<br /> class CMyClass:<br /> public CMyBase<br /> {<br /> public:<br /> CMyClass(){};<br /> virtual ~CMyClass(){};<br /> };</p><p> //這個聲明編譯時間會出錯<br /> CMyClass ab;<br />
當CMyClass繼承於CmyBase,並且聲明一個CmyClass對象時,那麼編譯器就會報如下錯誤:
error C2248: 'CMyBase::CMyBase' : cannot access private member declared in class 'CMyBase'
error C2248: 'CMyBase::~CMyBase' : cannot access private member declared in class 'CMyBase'
通過將建構函式和解構函式聲明為private的方式,就達到了讓類無法被繼承的目的。
接著來看看抽象,也就是類不能執行個體化,只能進行繼承。這個C++也能夠實現,但卻並不是很完美。我們都知道,C++的類什麼情況下不能執行個體化?就是類中帶有純虛函數的時候。藉助這個特性,我們也能實作類別不能執行個體化的目的,如下代碼所示:
class CMyBase<br /> {<br /> public:<br /> CMyBase(){};<br /> virtual ~CMyBase(){};</p><p> protected:<br /> //定義一個純虛函數,令該類不能執行個體化<br /> virtual void Abstract() = 0;<br /> };</p><p> class CMyClass:<br /> public CMyBase<br /> {<br /> public:<br /> CMyClass(){};<br /> virtual ~CMyClass(){};</p><p> protected:<br /> //必須要實現純虛函數,否則本類也不能執行個體化<br /> virtual void Abstract(){};<br /> };</p><p> //有純虛函數,該聲明有錯<br /> CMyBase MyBase;</p><p> //該聲明正確通過<br /> CMyClass MyClass;
雖然我們通過了純虛函數實現了類不能執行個體化的目的,但同時卻也帶出了純虛函數這個累贅,令子類為了執行個體化不得不實現這個沒有任何意義的純虛函數。相對而言,在這個方面,C#確實比C++要簡便很多。