1. 程式人生 > >C++類基礎

C++類基礎

  1. 關於空類

(1)C++中定義一個空的型別時類,裡面沒有任何成員變數和成員函式,對該型別求sizeof時,得到的結果應該是1,而不是0,因為空型別中不包含任何資訊,本來應該是0,但是當我們宣告該型別的例項的時候,必須在記憶體中佔有一定的空間,否則無法使用這些型別,至於佔用多少記憶體由編譯器決定,在Visual Studio中每個空型別的例項佔用一個位元組的空間。

(2)當在空類中新增一個建構函式和解構函式時若再求sizeof結果仍然是1,因為呼叫建構函式和解構函式只需要知道函式的地址即可,而這些函式的地址只與型別有關,而與型別的例項無關,編譯器也不會因為這兩個函式而在例項內新增任何額外的資訊。

(3)將解構函式標記為虛擬函式時:C++中編譯器一旦發現一個型別中有虛擬函式,就會為該型別生成虛擬函式表,並且在該型別的每一個例項中新增一個指向虛擬函式的指標。在32位的機器上,一個指標佔4位元組的空間,因此求sizeof得到的是4.在64位的機器上,一個指標佔8位元組的空間,因此求sizeof得到的是8.

  2.關於類

   (1)不說明訪問限定符時,函式預設為私有訪問

   (2)普通的成員變數呼叫時都要依賴物件來呼叫

  3.關於類中的預設成員方法

(1)建構函式:建構函式名與類名相同。作用是(1)開闢記憶體(2)給開闢的記憶體進行初始化  

                        :不帶引數的建構函式稱為預設建構函式 。建構函式可以過載。

                       :建構函式初始化以後不可再手動呼叫建構函式

(2)解構函式:作用清理資源,釋放記憶體。(棧上的系統自己清理,堆上的需要手動清理)

                       :先構造的後析構 不可過載 系統預設解構函式不會清理堆記憶體 如果不手動清除會導致記憶體洩漏

                       :解構函式可以自主呼叫,手動自主呼叫時即退化為普通成員方法

(3)拷貝建構函式:用一個已存在的物件生成一個相同型別的新物件。預設拷貝建構函式時淺拷貝,在有堆記憶體上的資料使用時會出錯。

                         :拷貝建構函式傳入的引數是一個const 類名& 型別的形參 ,因為&不用開闢新的空間,相當於指標指向實參類。而且使用引用可以防止遞迴呼叫拷貝構造形參物件的情況。const防止右運算元的物件被修改。

(4)賦值運算子的過載函式:將一個已存在的物件賦值給另外一個已存在的物件

       賦值運算子的過載函式實現步驟:①判斷是否為自賦值②釋放被賦值的資源③實現拷貝(淺拷貝,深拷貝,寫實拷貝)

     賦值運算子的過載函式的函式名 :例如:Goods& operator=(const CGoods& rhs)

      分析:①只有返回一個引用才可以允許連續賦值,否則如果函式的返回值是void,該賦值運算子將不能做連續賦值。例如CGoods有三個物件good1=good2=good3,就不能編譯通過。

               ②傳入的引數型別不是引用而是例項,那麼從形參到實參就會呼叫一次拷貝建構函式。設定為引用避免了無用的消耗。

              ③實現時的自賦值判斷:如果是同一個物件就不進行復制操作直接返回。如果不事先判斷,那麼在釋放物件的舊資源時就會出現嚴重問題。當this與傳入的引數是同一個物件是,一旦釋放了自身的記憶體,傳入的引數也被釋放了,就會出現錯誤。

//範例
	void operator=(const CGoods& rhs)
	{
		cout << this << "void operator=(const CGoods&)" << " <== " << &rhs << endl;
		if (this != &rhs)
		{
			delete[] mname;
		        mname = new char[strlen(rhs.mname) + 1]();
		        memcpy(mname, rhs.mname, strlen(rhs.mname) + 1);
		        mamount = rhs.mamount;
		        mprice = rhs.mprice;
		}
		return *this;
	}

在賦值運算子過載函式中還有以下問題需要注意:

①隱式生成臨時物件:good1=10;

   顯示生成臨時物件:good1=CGoods(10);

  這些臨時物件的生成周期在表示式結束

②在此函式中形參const的作用:一是防止實參被修改,二是接收隱式生成的臨時量

③類型別的返回值由臨時物件帶出來,呼叫函式時形參會先呼叫拷貝建構函式生成臨時物件。

④臨時物件的優化:臨時物件的生成目的如果是為了生成新的物件則會以生成臨時物件的方式來生成新的物件。

⑤禁止隱式生成臨時物件關鍵字:explicit