函式可以擁有同樣的函式名,但引數列表(引數的個數、引數的型別)不同。
如果兩個函式擁有同樣的函式名、引數列表,但是返回值不同,這種情況不是函式過載。例如
void
bigger
(double a,
double b)
double
bigger
(double a,
double b)
以上兩個函式的本質是相同的,編譯器呼叫時會出現二義性,即出現了函式的重複。
引用(起別名)要求定義必須做初始化,即
int a =10;
int&r = a;
int*p =
&a;cout << r << endl;
cout <<
*p << endl;
引用不會占用記憶體資源,而指標需要額外申請記憶體空間;
另外,指標還需要額外的一次解引用操作,而引用不需要。在函式的引數中,引用得到乙個很好的應用。
引用作為函式返回值:
語法:型別 &函式名(形參列表)
1、引用作為函式的返回值時,必須在定義函式時在函式名前加&;
2、用引用作函式的返回值的最大的好處是在記憶體中不產生返回值的副本。
int
&value
(int r)
但像下面的使用,可能存在風險
int
&value()
因為區域性變數是儲存在棧中,當返回時可能由於區域性變數銷毀而無法獲取值。
所以對於引用做函式的返回值,需要注意以下幾點:
(1)不能返回區域性變數的引用。主要原因是區域性變數會在函式返回後被銷毀,因此被返回的引用就成為了"無所指"的引用,程式會進入未知狀態。
(2)不能返回函式內部new分配的記憶體的引用。雖然不存在區域性變數的被動銷毀問題,可對於這種情況(返回函式內部new分配記憶體的引用),又面臨其它尷尬局面。例如,被函式返回的引用只是作為一 個臨時變數出現,而沒有被賦予乙個實際的變數,那麼這個引用所指向的空間(由new分配)就無法釋放,造成memory leak。
(3)可以返回類成員的引用,但最好是const。主要原因是當物件的屬性是與某種業務規則(business rule)相關聯的時候,其賦值常常與某些其它屬性或者物件的狀態有關,因此有必要將賦值操作封裝在乙個業務規則當中。如果其它物件可以獲得該屬性的非常量引用(或指標),那麼對該屬性的單純賦值就會破壞業務規則的完整性。
c++ 中對類的宣告有兩種方式:
1、
class
person()
;
2、
struct
man(
);
以上兩種都可以完成類的宣告,區別體現在封裝和繼承特性上,其他在使用時基本是一樣的。
為什麼會產生這樣的現象呢?
c++ 是用 c 語言寫的,而c語言中沒有類的概念,只有結構體,因此 c++ 的類和結構體,回歸於 c 語言的結構體。
類相當於乙個模板,或者當成特徵歸總。
生成物件的三種方式:
1、隱式宣告物件
person p1;
//存放在棧區
2、顯式生成物件
person p1 =
person()
;//存放在棧區
3、顯式生成物件,使用new
關鍵字
person *p3 =
newperson()
;//返回的是記憶體的位址,所以需要指標接收
//存放在堆區
delete p3;
class
定義的類,預設的封裝是private
,成員變數是私有的,只能在本類的內部進行訪問;struct
定義的類,預設的封裝是public
,成員變數是公有的,可以在類的外部進行使用。
還會遇到另外一種封裝protected
,表示在外部成員變數是私有的,在類的派生類,成員變數是公有的。
類外定義成員函式的方法:(一定要新增網域名稱!)
class
person
;
這裡只是進行宣告,沒有具體實現,然後在類的外部去定義函式的實現
void
displayage()
此時編譯會報錯error: use of undeclared identifier 'age'
,這是因為,外部的函式和類並沒有進行聯合,只是普通的定義,所以外部的displayage()
並不知道age
是從**來的。該問題可以通過下面的方式進行解決:
void person::
displayage()
注意:成員函式也必須滿足封裝的特性。
對於成員變數的訪問,隱式呼叫了this
指標,this
指標指向呼叫函式的物件。
在平時的使用中,this
指標是不需要進行顯式操作的。
在下面的情況中會用到this
class
person
;
person &person::
getcurrentobject()
直接在class
宣告中進行完整的定義乙個函式
class
person
};
其實,在類內定義成員函式,有乙個隱藏的宣告,即inline
inline
class
person
};
用inline
標記頻繁呼叫、內部邏輯較簡單的函式,可以提高編譯處理的效率。如果是類外部進行定義的,需要顯式宣告inline
。
person p1;
在通過類建立物件時,編譯器會預設呼叫乙個建構函式。
如果要顯式定義乙個建構函式,可以通過以下方式
class
person
};
顯式呼叫
person p1 =
person(18
,'m'
,100.1
);
當然,建構函式也可以進行過載。
初始化成員列表的使用
person
(int a)
:age
(a)
預設建構函式的第一種形式:
person()
;
如果想要有內容去展示和匹配,就有預設建構函式的第二種形式:
person
(int a =18)
;
也可以簡化為
person
(int a =18)
:age
(a);
注意:要在引數列表對每乙個形參賦值。
person p2 = p1;
p2.display()
;
此時 p2 並沒有呼叫類中的建構函式,而是呼叫的拷貝建構函式。
person
(person &p)
:age
(p.age)
如果沒有顯式的定義建構函式和拷貝建構函式,那麼編譯器會自動合成預設的建構函式和拷貝建構函式。
每次申請一塊空間時,有乙個時間段總會去釋放,釋放的時候就會呼叫類中的析構函式。
~
person()
析構函式以~
開頭,後面跟類名;
析構函式不能帶引數;
析構函式沒有返回值;
析構函式不能過載;
析構函式不能顯式呼叫,而是由系統自定義呼叫方式;
如果沒有顯式定義,系統會自動生成析構函式。
而對於動態生成的物件,需要使用delete關鍵字呼叫析構函式。
person *p3 =
newperson()
;delete p3;
當在類中動態申請記憶體空間之後,需要在析構函式中使用free()
釋放空間,否則會導致記憶體洩漏。
陣列型別的物件建立
//1、
person p1[3]
;//2、
person *p2 =
new person[3]
;
這裡1和2兩種方式是有區別的,第一種建立的物件儲存在棧區,呼叫完後會自動呼叫析構函式進行釋放;
第二種建立的物件儲存在堆區,但使用完後,不會主動去釋放空間。
delete
p2;//動態物件陣列的釋放
C 學習筆記( )
一 語法 迴圈 foreach 型別識別符號 in 表示式 code 用法 例子int temp foreach int num in temp 每次從temp取乙個元素賦給num直至取完 console.writeline n num 每行顯示乙個元素 執行結果 c 中唯讀 只寫控制 class ...
C 學習筆記
1.函式特徵 有函式頭和函式體 接受乙個引數 返回乙個值 需要乙個原型。2.c 命名規則 在名稱中只能使用字母字元 數字和下劃線 名稱的第乙個字元不能是數字 區分大寫字母和小寫字母 不能將c 關鍵字用作名稱 以兩個下劃線或下劃線和大寫字母打頭的名稱被保留給實現 編譯器及其使用的資源 使用,以乙個下劃...
c 學習筆記
屬性 屬性開頭字母大寫 屬性可以判斷輸入的非法值 屬性本身不儲存值 依靠字段 索引器 using system using system.collections.generic using system.linq using system.text namespace b try catch exc...