//=====================================================================
//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。也就是說,這兩種語言都可以這樣聲明一個類:
view plaincopy to clipboardprint?
class CMyClass
{
//Class members
};
class CMyClass
{
//Class members
};
至此,C++的聲明就是如此了。但C#還在此基礎上再度發展,在class之前還有internal和public兩個關鍵字可選。默認的情況下,類聲明是內部的,只有當前項目的代碼才能訪問它,換句話來說,上面的聲明在C#中相當於如此:
view plaincopy to clipboardprint?
internal class CMyClass
{
//Class members
};
internal class CMyClass
{
//Class members
};
如果想在別的項目中也能使用該代碼,那麼必須用public來進行修飾,如:
view plaincopy to clipboardprint?
public class CMyClass
{
//Class members
};
public class CMyClass
{
//Class members
};
除了這兩個訪問修飾以外,還能指定類是否是抽象的,或密封的。抽象的關鍵字是abstract,表明其不能實例化,只能繼承;密封的關鍵字是sealed,表示其不能被繼承。從意思上我們就可以知道,這兩個關鍵字是互斥的,兩者只能選擇其一。
如果我們聲明一個抽象的公共類,代碼可以書寫如下:
view plaincopy to clipboardprint?
public abstract class CmyClass
{
//Class members
}
public abstract class CmyClass
{
//Class members
}
public和abstract這兩個關鍵字的次序無關緊要,可以隨意顛倒。
我們來討論一個很有意思的問題,C++沒有這兩個關鍵字,是不是就沒辦法實現類似於C#的功能了呢?答案當然不是了。我們來看看,如何用C++來實現C#的這兩個特性。
首先來看的是密封,也就是不能讓這個類被繼承。雖然C++沒有sealed關鍵字,但實現這個功能一點也不費功夫,我們只要將構造函數或析構函數聲明為private即可,如下代碼所示:
view plaincopy to clipboardprint?
//父類
class CMyBase
{
//將構造函數和析構函數聲明為private
private:
CMyBase(){};
virtual ~CMyBase(){};
};
//子類
class CMyClass:
public CMyBase
{
public:
CMyClass(){};
virtual ~CMyClass(){};
};
//這個聲明編譯時會出錯
CMyClass ab;
//父類
class CMyBase
{
//將構造函數和析構函數聲明為private
private:
CMyBase(){};
virtual ~CMyBase(){};
};
//子類
class CMyClass:
public CMyBase
{
public:
CMyClass(){};
virtual ~CMyClass(){};
};
//這個聲明編譯時會出錯
CMyClass ab;
當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++的類什麼情況下不能實例化?就是類中帶有純虛函數的時候。借助這個特性,我們也能實現類不能實例化的目的,如下代碼所示:
view plaincopy to clipboardprint?
class CMyBase
{
public:
CMyBase(){};
virtual ~CMyBase(){};
protected:
//定義一個純虛函數,令該類不能實例化
virtual void Abstract() = 0;
};
class CMyClass:
public CMyBase
{
public:
CMyClass(){};
virtual ~CMyClass(){};
protected:
//必須要實現純虛函數,否則本類也不能實例化
virtual void Abstract(){};
};
//有純虛函數,該聲明有錯
CMyBase MyBase;
//該聲明正確通過
CMyClass MyClass;
class CMyBase
{
public:
CMyBase(){};
virtual ~CMyBase(){};
protected:
//定義一個純虛函數,令該類不能實例化
virtual void Abstract() = 0;
};
class CMyClass:
public CMyBase
{
public:
CMyClass(){};
virtual ~CMyClass(){};
protected:
//必須要實現純虛函數,否則本類也不能實例化
virtual void Abstract(){};
};
//有純虛函數,該聲明有錯
CMyBase MyBase;
//該聲明正確通過
CMyClass MyClass;
雖然我們通過了純虛函數實現了類不能實例化的目的,但同時卻也帶出了純虛函數這個累贅,令子類為了實例化不得不實現這個沒有任何意義的純虛函數。相對而言,在這個方面,C#確實比C++要簡便很多。