程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> C語言基礎知識 >> 第五章 類 (1)

第五章 類 (1)

編輯:C語言基礎知識
第五章  類(1)
       前一章討論了數據類型和它們的用法。現在我們轉移到C#中至關重要的結構——類。沒有了類,就連簡單的C#程序都不能編譯。這一章假定你知道了一個類的基本組成部分:方法、屬性、構造函數和析構函數。 C#在其中增加了索引和事件。
       在這一章中,你學到下列有關類的話題。
      。 使用構造函數和析構函數
      。給類寫方法
      。給一個類增加屬性存取標志
      。實現索引
      。創建事件並通過代表元為事件關聯客戶
      。應用類、成員和存取修飾符。

5.1  構造函數和析構函數
          在你可以訪問一個類的方法、屬性或任何其它東西之前, 第一條執行的語句是包含有相應類的構造函數。甚至
你自己不寫一個構造函數,也會有一個缺省的構造函數提供給你。

class TestClass
{
public TestClass(): base() {} // 由編譯器提供
}

       一個構造函數總是和它的類名相同,但是,它沒有聲明返回類型。總之,構造函數總是public的,你可以用它們來
初始化變量。

public TestClass()
{
// 在這給變量
// 初始化代碼等等。
}

       如果類僅包含靜態成員(能以類型調用,而不是以實例調用的成員),你可以創建一個private的構造函數。
private TestClass() {}
       盡管存取修飾符在這一章的後面將要大篇幅地討論,但是private意味著從類的外面不可能訪問該構造函數。所
以,它不能被調用,且沒有對象可以自該類定義被實例化。
       並不僅限於無參數構造函數——你可以傳遞初始參數來初始化成員。
       public TestClass(string strName, int nAge) { ... }

       作為一個C/C++程序員,你可能習慣於給初始化寫一個附加的方法,因為在構造函數中沒有返回值。當然,盡管在
C#中也沒有返回值,但你可以引發一個自制的異常,以從構造函數獲得返回值。更多有關異常處理的知識在第七章 "異常
處理"中有討論。
       但是,當你保留引用給寶貴的資源,應該想到寫一個方法來解決:一個可以被顯式地調用來釋放這些資源。問題是
當你可以在析構函數(以類名的前面加"~"的方式命名)中做同樣的事情時,為何還要寫一個附加的方法.
public ~TestClass()
{
// 清除
}

    你應該寫一個附加方法的原因是垃圾收集器,它在變量超出范圍後並不會立即被調用,而僅當間歇期間或內存條件滿
足時才被觸發。當你鎖住資源的時間長於你所計劃的時間時,它就會發生。因此,提供一個顯式的釋放方式是一個好主
意,它同樣能從析構函數中調用。

public void Release()
{
// 釋放所有寶貴的資源
}

public ~TestClass()
{
Release();
}

    調用析構函數中的釋放方法並不是必要的——總之,垃圾收集會留意釋放對象。但沒有忘記清除是一種良好的習慣。

5.2  方法
     既然對象能正確地初始化和結束,所剩下來的就是往類中增加功能。在大多數情況下,功能的主要部分在方法中能得
到實現。你早已見過靜態方法的使用,但是,這些是類型(類)的部分,不是實例(對象)。
    為了讓你迅速入門,我把這些方法的煩瑣問題安排為三節:
。方法參數
。改寫方法
。方法屏蔽
5.2.1  方法參數
  因方法要處理更改數值,你多多少少要傳遞值給方法,並從方法獲得返回值。以下三個部分涉及到由傳遞值和為調用者
獲取返回結果所引起的問題。

。輸入參數
。引用參數
。輸出參數

5.2.1.1  輸入參數
  你早已在例子中見過的一個參數就是輸入參數。你用一個輸入參數通過值傳遞一個變量給一個方法——方法的變量被調
用者傳遞進來的值的一個拷貝初始化。清單5.1 示范輸入參數的使用。

清單  5.1 通過值傳遞參數

1: using System;
2:
3: public class SquareSample
4: {
5:  public int CalcSquare(int nSideLength)
6:  {
7:   return nSideLength*nSideLength;
8:  }
9: }
10:
11: class SquareApp
12: {
13:  public static void Main()
14:  {
15:   SquareSample sq = new SquareSample();
16:   Console.WriteLine(sq.CalcSquare(25).ToString());
17:  }
18: }

   因為我傳遞值而不是引用給一個變量,所以當調用方法時(見第16行),可以使用一個常量表達式(25)。整型結果被傳回
給調用者作為返回值,它沒有存到中間變量就被立即顯示到屏幕上 。
    輸入參數按C/C++程序員早已習慣的工作方式工作。如果你來自VB,請注意沒有能被編譯器處理的隱式ByVal或ByRef—
—如果沒有設定,參數總是用值傳遞。
     這點似乎與我前面所陳述的有沖突:對於一些變量類型,用值傳遞實際上意味著用引用傳遞。迷惑嗎? 一點背景知識
也不需要:COM中的東西就是接口,每一個類可以擁有一個或多個接口。一個接口只不過是一組函數指針,它不包含數據。
重復該數組會浪費很多內存資源;所以,僅開始地址被拷貝給方法,它作為調用者,仍然指向接口的相同指針。那就是為
什麼對象用值傳遞一個引用。

5.2.1.2  引用參數
    盡管可以利用輸入參數和返回值建立很多方法,但你一想到要傳遞值並原地修改它(也就是在相同的內存位置),就沒
有那麼好運了。這裡用引用參數就很方便。
void myMethod(ref int nInOut)
   因為你傳遞了一個變量給該方法(不僅僅是它的值),變量必須被初始化。否則,編譯器會報警。清單 5.2 顯示如何用
一個引用參數建立一個方法。

清單 5.2  通過引用傳遞參數

1: // class SquareSample
2: using System;
3:
4: public class SquareSample
5: {
6:  public void CalcSquare(ref int nOne4All)
7:  {
8:   nOne4All *= nOne4All;
9:  }
10: }
11:
12: class SquareApp
13: {
14:  public static void Main()
15:  {
16:   SquareSample sq = new SquareSample();
17:
18:   int nSquaredRef = 20; // 一定要初始化
19:   sq.CalcSquare(ref nSquaredRef);
20:   Console.WriteLine(nSquaredRef.ToString());
21:  }
22: }

   正如所看到的,所有你要做的就是給定義和調用都加上ref限定符。因為變量通過引用傳遞,你可以用它來計算出結果
並傳回該結果。但是,在現實的應用程序中,我強烈建議要用兩個變量,一個輸入參數和一個引用參數。

5.2.1.3  輸出參數
   傳遞參數的第三種選擇就是把它設作一個輸出參數。正如該名字所暗示,一個輸出參數僅用於從方法傳遞回一個結果。
它和引用參數的另一個區別在於:調用者不必先初始化變量才調用方法。這顯示在清單5.3中。

清單  5.3  定義一個輸出參數

1: using System;
2:
3: public class SquareSample
4: {
5:  public void CalcSquare(int nSideLength, out int nSquared)
6:  {
7:   nSquared = nSideLength * nSideLength;
8:  }
9: }
10:
11: class SquareApp
12: {
13:  public static void Main()
14:  {
15:   SquareSample sq = new SquareSample();
16:   
17:   int nSquared; // 不必初始化
18:   sq.CalcSquare(15, out nSquared);
19:   Console.WriteLine(nSquared.ToString());
20:  }
21: }


5.2.2  改寫方法
    面向對象設計的重要原則就是多態性。不要理會高深的理論,多態性意味著:當基類程序員已設計好用於改寫的方法
時,在派生類中,你就可以重定義(改寫)基類的方法。基類程序員可以用 virtual 關鍵字設計方法:
virtual void CanBOverridden()
    當從基類派生時,所有你要做的就是在新方法中加入override關鍵字:
override void CanBOverridden()
    當改寫一個基類的方法時,你必須明白,不能改變方法的訪問屬性——在這章的後面,你會學到更多關於訪問修飾符
的知識。
    除了改寫基類方法的事實外,還有另一個甚
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved