程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 一個基本問題引出的話題,類常識你知多少?,引出的話題類常識

一個基本問題引出的話題,類常識你知多少?,引出的話題類常識

編輯:C++入門知識

一個基本問題引出的話題,類常識你知多少?,引出的話題類常識


以前覺得吧,寫文章純屬浪費時間,有那麼點時間還不如玩會游戲、和姑娘聊聊天。現在這覺得,寫寫讀書筆記也是好的,一來信息分享,(各個雲平台不就是分享、然後大數據麼)二來溫故而知新,加深了對知識的理解。話不多說,繼續寫

    問題:在C++中一個空類,他會產生多少個函數呢?

    答案還是慢慢揭曉,首先介紹C++幾個成員函數。

    構造函數:

    什麼是構造函數?構造函數的作用又是什麼?可以有多少個構造函數?

    首先,構造函數是類中一種特殊的成員函數,它和類是同名的、沒有返回值。構造函數的作用是什麼?我個人覺得他主要是用來提供類的各種初始化。

    剛剛我講到了各種初始化,想必大家也就知道了構造函數是可以多個的。

    在我們沒有顯示的定義構造函數的時候,編譯器會自動生成一個構造函數,這個構造函數是不帶參數的;當然,如果我們已經在類中顯示的定義了若干或者一個構造函數,那麼編譯器就不會生成一個構造函數了。比如有一個類Class A;

復制代碼
1 class A{
2 public:
3      A(int a){
4         b=a;
5         cout<<b;
6     }
7 private:
8     int b;
9 };
復制代碼

     在這個類中,我定義了一個帶有一個整形參數的構造函數,這就意味著如果我們要New一個新的對象只能傳遞一個int參數。如果不傳遞參數就會報錯,這也間接說明了,定義了構造函數就不會參數默認構造函數了。

    所以,如果我們需要一個無參數的構造函數,就必須顯示的定義。一般來說,定義了一個帶參數的構造函數就要定義無參數的構造函數,這主要從安全和方便的角度來考慮的。因為我們經常是A x=new A();如果沒有定義無參數構造函數,我們可能連錯在哪裡都不知道。

   這裡說到了構造函數的主要功能是初始化成員數據。上面已經提供了一種初始化方式,還有一種初始化方式是class A:b(5){};

   需要注意的是在C++成員變量的初始化順序是按照聲明的順序保持一致的。而以構造函數的初始化順序無關。

 

   一種特殊的構造函數:復制構造函數

   注意,這裡是復制,而不是賦值。

   復制構造函數其實就是對象的拷貝過程。例子如下。

1      A(const A &other){
2          this->b=other.b;
3          cout<<this->b;
4      }

   還有一種是賦值。下面即是。其中x賦值到m。

1 A x(6),m=x;

  談到復制構造函數的話,有必要強調一下深復制和淺復制的概念。也稱為深拷貝、淺拷貝

   先澄清我這裡的兩個概念,如果對象A復制到B,則稱A為原對象,B為新對象。

   淺復制是指新對象所有變量都含有原對象的值,但是引用仍然指向原對象。

   深復制是指新對象所有的變量都含原有對象的值,並且所有的引用也進行了復制。

   這個怎麼理解呢?其實就是淺復制之後,引用還是對原對象的(所以一旦原對象指針釋放,新對象的指針就不知道指向何處了,野孩子就是這樣出現的)。而深復制,把引用也復制了(創建了自己的資源,原對象再折騰也影響不到我)。具體例子見下面。

復制代碼
 1 struct Test{
 2     char *ptr;
 3 };
 4 void shallow_copy(Test &dest,const Test &source){//淺復制
 5     dest.ptr=source.ptr;
 6 }
 7 void deep_copy(Test &dest,const Test &source){//深復制
 8     dest.ptr=(char*)malloc(strlen(source.ptr)+1);
 9     memcpy(dest.ptr,source.ptr,strlen(source.ptr)+1);
10 }
復制代碼

    淺拷貝很容易造成程序崩潰,比如說原對象中有動態指針,如果淺拷貝,那麼新對象指向的還是原對象的指針,如果原對象釋放掉了.那麼新對象指向哪裡??

    更多這方面的知識請查閱相關文章。

    析構函數

    與構造函數相對的是構造函數,構造函數是初始化對象成員,那麼析構函數就是釋放資源的,一般析構函數都是最後退出的時候執行的。

    定義的話類似構造函數,在構造函數加一個~,比如~A(){};

    另外析構函數無參數,無返回值,也只能有一個析構函數。

    在繼承中,比如son類繼承parent類,son littleson;這個過程是先調用父類parent的構造函數,再調用son類的構造函數;析構函數則是一個相反的過程,先調用子類的析構函數,再調用父類的析構函數。其實這個我們從資源的分配和回收角度很容易理解。

    

    談到資源的分配,我們知道編譯器自動分配是在棧中進行,程序員申請資源和釋放資源是在堆中進行的。

    在C++中資源的申請有兩種不同的方式,New,malloc,想對應的釋放也有兩種方式delete,free.我們分析一下這兩種方式的異同。

    相同的我們就不多說了,都可以進行資源的動態申請是他們最大的相同之處了,那麼異呢?

    1、malloc是調用函數,而new 是運算符

     2、malloc需要計算申請的字節數,並轉化成相應類型;而new則是自動計算的。

     3、malloc是不安全的,而New是安全的(申請的時候不會出現編譯出錯)如:int p=(int)malloc(sizeof(double));

    4、maolloc需要庫文件的支持,函數肯定需要呀,而new 不需要,因為人家是運算符啊,你想想+須有庫文件就知道了嘛。

     5、new會調用構造函數,delete調用析構函數。

   那麼似乎new比malloc牛b多了,我們就不需要malloc了呢?

   malloc是一種舊式的資源申請模式,現在都提倡new申請這是無疑的。但是有一種情況用malloc會取得比較好的效果,就是當程序在一次申請之後,可能會使用完畢需要再次申請的時候,因為有realloc啊。當然也可以用vector.

    

    現在可以回答最開始的問題了,它會產生的成員函數至少包括:構造函數,析構函數,復制構造函數,取址運算符重載函數,賦值運算符重載函數,const取址運算符重載函數。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved