什麼叫做面向過程程式設計?
通俗的來說,這種程式設計風格如同從上到下,從左到右。首先,要考慮遵循的步驟,然後考慮如何表現這些資料。
那麼什麼又是物件導向程式設計呢?
從使用者的角度出發考慮物件,描述物件所需的資料以及描述使用者與資料進行互動所需要的操作。完成對介面的描述後,需要確定如何實現介面和資料儲存。
特點:封裝、繼承、多型
封裝:資料進行隱藏,把不想讓外部使用的資料狀態隱藏起來;
繼承:實現**復用;
多型:實現功能的擴充套件。
抽象和類
抽象:將問題的本質抽取出來,並根據特徵來描述解決方案;
類:類是一種將抽象轉化為使用者定義型別的c++工具,他將資料的表示和操縱的方法組合成乙個整潔的包;
下面,舉乙個圓的例子進行說明:
#include
using
namespace
std;
const
int pi = 3.14;
class circle
void prints()
;int main()
說明:這個圓類中包含了兩個成員,半徑(m_r)和面積(m_s),這兩個成員就代表了圓的屬性。圓類中,還有兩個方法,乙個求取面積,乙個用來列印,都是對資料的操縱,可以看出,這些屬性和方法都是在這個class circle中,也就是說,類中包含了物件的屬性、包含了對物件的操縱的函式。像這樣的形式,物件導向程式設計。
不難發現,這種類的形式與結構體十分相像,其實在c++的內部,類也的確是由結構體進行實現的。那麼這兩者的區別在哪呢?
1.在c++中,結構體內部允許設定訪問許可權,預設訪問許可權是公有,而類的預設訪問許可權是私有。
2.定義乙個結構體,可以直接用「=」進行初始化,但類只能使用建構函式進行初始化;
類的內部成員(變數和函式)訪問許可權:
三種:public、private、protected
public:公有屬性,類的內部和外部都可以訪問;
protected:保護屬性,類的內部可以訪問,外部不可訪問;
private:私有屬性,類的內部和外部都不可以訪問。
建構函式和析構函式
建構函式:類的物件使用建構函式完成初始化
1.函式名與類名相同;
2.沒有返回值;
3.不需要手動呼叫(一般情況下),系統自動呼叫。
析構函式:**資源
1.函式名與類名相同,函式名前加~;
2.沒有返回值;
3.**物件資源,當物件被釋放時,系統自動呼叫。
注意:
建構函式可以過載,析構函式不可過載
建構函式又分為無參構造、有參構造。
還是以上面的圓類進行說明:
#include
using
namespace
std;
const
int pi = 3.14;
class circle
circle(int r)
~circle()
double calus()
void prints()
;int main()
那麼建構函式被呼叫的情形有哪些?
1.使用括號()
circle c1; 呼叫無參構造
cirlcle c2(2);呼叫乙個引數的建構函式
2.用「=」號
circle c1 = 4; ==> circle c1(4)
circle c2 = (2, 3);==> circle c2(3) ,其後的(2, 3)其實是乙個逗號表示式
3.手動呼叫
circle c1 = circle(); ==> circle c1
circle c2 = circle(2);==> circle c2(2)
拷貝建構函式:用乙個物件對另外乙個物件進行初始化時,系統會自動呼叫;
呼叫的情形如下:
1.
circle c1(1, 2);
circle c2(c1); ==> circle c2(circle c1);
2.circle c1(1, 2);
circle c2 = c1; ⇒ circle c2(c1);
3.circle c1(1, 2);
circle c2 = circle(c1);
注意:circle c1(1, 2);
circle c2;
c2 = c1; ??? 會呼叫拷貝建構函式嗎?
答案是否定的,上述的形式只是賦值,並不是初始化,呼叫拷貝建構函式必須是初始化的時候。
4.當乙個函式的形參是乙個物件時,會呼叫拷貝建構函式
//circle obj = c1; 因此,在引數傳遞時,要傳物件的引用或者指標
void func(circle obj)
int main()
5.物件作為函式的返回值時
circle func()
在物件作為函式返回值時,會涉及到乙個匿名物件的處理,分為三種情況:
1.返回值不被接受時
2.用新物件去接收時
3.用乙個已經存在的物件去接收時
預設建構函式如果類中沒有定義拷貝建構函式,編譯器會預設新增乙個拷貝建構函式,這個拷貝建構函式進行的是變數「值」的複製,不會複製堆上的空間。==>淺拷貝
自己編寫拷貝建構函式,實現堆上空間的複製。==>深拷貝
下面舉個例子說明淺拷貝與深拷貝的區別:
#include
using
namespace
std;
class student
~student()
void print()
private:
int m_age;
char *m_name;
};int main()
//上述**,在執行時會有段錯誤發生,錯誤原因在於堆上的位址二次釋放,下面解釋一下為什麼使用預設拷貝建構函式會出現這種情況。
當定義物件 stu1 時,會在堆上開闢 20 位元組的空間用來存放名字,當使用 stu1 初始化 stu2 時,預設拷貝建構函式只是執行簡單的「值」的複製,所以 stu2 的名字與 stu1 指向的是同一塊位址,因此在析構的時候,會對 0x1000 這塊位址釋放兩次,於是便發生了段錯誤。
那麼為了避免這種情況的發生,需要自己寫乙個拷貝建構函式。
#include
using
namespace
std;
class student
~student()
student(const student &obj) //自己編寫的拷貝建構函式
void print()
private:
int m_age;
char *m_name;
};int main()
分析一下,為什麼這樣就不會出錯了呢?
當定義物件 stu1 時,會在堆上開闢 20 位元組的空間(0x1000)用來存放名字,當使用 stu1 初始化 stu2 時,會呼叫自己編寫的拷貝建構函式,在函式體內,我們對 m_name 也開闢了20位元組的空間(0x2000),這樣兩個物件的 m_name就指向不同的位址,析構時也不會出現對同一塊位址重複釋放的錯誤。
27 物件導向程式設計
物件導向程式設計 物件導向程式設計 object oriented programming,簡稱oop,是一種程式設計方法。物件導向面向過程區別 完成自我介紹功能,面向過程完成功能 stu a stu b stu c def stu info stu 自我介紹 for key,value in st...
Python學習 27 物件導向程式設計4
這一節我們來繼續介紹物件導向程式設計。涉及到的內容有property屬性和運算子的過載。1.property屬性 之前的物件導向程式設計中,我們介紹了兩種訪問屬性的方式。第一種是物件名.屬性名,這種直接訪問屬性的方式 第二種是使用get和set方法訪問屬性。第二種方式 的靈活性比第一種要高,並且第二...
Python學習 27 物件導向程式設計4
這一節我們來繼續介紹物件導向程式設計。涉及到的內容有property屬性和運算子的過載。1.property屬性 之前的物件導向程式設計中,我們介紹了兩種訪問屬性的方式。第一種是物件名.屬性名,這種直接訪問屬性的方式 第二種是使用get和set方法訪問屬性。第二種方式 的靈活性比第一種要高,並且第二...