复习笔记(二)——C++面向对象设计和使用
面向?qū)ο缶幊?OOP)
面向?qū)ο?#xff08;Object Oriented )是認識事務的一種方法,是一種以對象為中心的思維方式
面向?qū)ο蟮某绦蛟O計:
對象=(算法+數(shù)據(jù)結(jié)構(gòu))
程序=對象+對象+……+對象
面向?qū)ο蟪绦蛟O計模擬自然界認識和處理事物的方法,將數(shù)據(jù)和對數(shù)據(jù)的操作方法放在一起,形成一個相對獨立的整體——對象(object),同類對象還可抽象出共性,形成類(class )。一個類中的數(shù)據(jù)通常只能通過本類提供的方法進行處理,這些方法成為該類與外部的接口。對象之間通過消息(message)進行通訊。
我們把對象之間產(chǎn)生相互作用所傳遞的信息稱做消息。
C++將“向?qū)ο蟀l(fā)消息”處理成“調(diào)用對象的某個成員函數(shù)”
基本概念——對象
世界上所有的事物都可以稱為對象(Object)。對象可以是有形的如:一臺電視機等。也可以是無形的如:帳戶、一項記錄等。
一個對象就是一個獨立存在的客觀事物,它由一組屬性和對屬性進行操作的一組操作構(gòu)成。
- 屬性是對象靜態(tài)特征的描述
- 操作是對象動態(tài)特征的描述
屬性和操作是對象的兩大要素。如電視的屬性有:品牌、尺寸、重量等。操作有:收視、選臺、音量調(diào)節(jié)等。
基本概念——類
類是一個抽象的概念,用來描述某一類對象所共有的、本質(zhì)的屬性和類行為。
類實根據(jù)抽象的原則對客觀事物進行歸納和劃分。
面向?qū)ο蟮幕咎卣?/h1>
- 抽象
- 封裝和數(shù)據(jù)隱藏(簡單介紹)
- 繼承
- 多態(tài)
封裝和數(shù)據(jù)隱藏
封裝是指按照信息屏蔽的原則,把對象的屬性和操作結(jié)合在一起,構(gòu)成一個獨立的對象。
通過限制對屬性和操作的訪問權限,可以將屬性“隱藏”在對象內(nèi)部,對外提供一定的接口,在對象之外只能通過接口對對象進行操作。
封裝性增加了對象的獨立性,從而保證了數(shù)據(jù)的可靠性。
外部對象不能直接操作對象的屬性,只能使用對象提供的服務。
抽象的設計思路
數(shù)據(jù)抽象化為屬性
處理過程抽象化為操作(方法)
-例如:當建立一個圖書管理系統(tǒng)時,通過直覺知道系統(tǒng)里一定要有圖書管理員/讀者/書這些對象, 而其中讀者的行為含有借書/還書,學生還有其相應的學號/姓名/班級等內(nèi)容
類的定義
C++通過建立數(shù)據(jù)類型——類來支持封裝和數(shù)據(jù)隱藏。一個定義完好的類可以作為獨立模塊使用。
類的定義格式分為說明部分和實現(xiàn)部分
—說明部分包含數(shù)據(jù)成員和成員函數(shù)說明
—實現(xiàn)部分是用來對成員函數(shù)的定義
類的一般定義格式如下:
class <類名> {public :<公有數(shù)據(jù)成員和成員函數(shù)>;protected:<保護數(shù)據(jù)成員和成員函數(shù)>;private :<私有數(shù)據(jù)成員和成員函數(shù)>; };class是定義類的關鍵字是數(shù)據(jù)類型說明符,<類名>是一個標識符,用于唯一地標識一個類(新的數(shù)據(jù)類型),類名后面花括號擴起來的部分是類體(Class Body)。
類體中定義了類成員表(Class Member List)
—數(shù)據(jù)成員(Data Member)
—函數(shù)(Member Function)
public、protected和private是訪問限定符(access specifier)
一般在類體內(nèi)先說明公有成員,它們是用戶所關心的,后說明私有成員,它們是用戶不感興趣的,但此順序并不是必須的。
***注意:
①在類的說明部分之后必須加分號“;”。
②類的定義放在一個頭文件中(.h),供其它需要使用該類的文件包含
③類的實現(xiàn)部分放在一個源文件中(.cpp),該文件需要包含定義類的頭文件
④類的定義和實現(xiàn)可以放在一個文件里,但不提倡,因為結(jié)構(gòu)不清晰,影響了程序的可讀性
數(shù)據(jù)成員(屬性)
類中的數(shù)據(jù)成員的類型可以是任意的,可以定義各種類型的變量、指針、數(shù)組等,甚至是其他類的對象。
在說明數(shù)據(jù)成員時,一般按數(shù)據(jù)成員的類型大小,由小到大說明,這樣可提高空間利用率。
在類的定義中只能聲明數(shù)據(jù)成員,不允許對所定義的數(shù)據(jù)成員進行初始化。
類的數(shù)據(jù)成員只能在類里聲明,類的數(shù)據(jù)成員最好都是私有的
外部函數(shù)需要修改它,一般也只給它提供公有函數(shù)接口,讓它通過類的公有成員函數(shù)訪問類的私有數(shù)據(jù)數(shù)據(jù)成員也可以放在public部分,但不提倡
成員函數(shù)(方法)
成員函數(shù)可以直接使用類定義中的任一成員,可以處理數(shù)據(jù)成員,也可調(diào)用成員函數(shù)。
類的成員函數(shù)定義通常可采取兩種方式,即外部定義和內(nèi)部定義(不推薦!影響到了程序的可讀性)。
成員函數(shù)的實現(xiàn)一般放在類的外面,在類里面對函數(shù)的原型進行聲明
成員函數(shù)的實現(xiàn)在類的定義外面時,必須聲明其所屬,在函數(shù)名前加類名和作用域運算符“::”,用來表示某個成員函數(shù)屬于哪個類的,定義格式如下:
返回類型 類名::成員函數(shù)名(參數(shù)說明) {函數(shù)體 }類成員函數(shù)的實現(xiàn)也可以放在類里,不需要加類名和作用域運算符
訪問控制
三個訪問說明符:public、private和protected
作用:控制對類的成員的訪問
在用class定義的類中,默認的訪問方式是private
在類的定義中,三個訪問說明符都可以使用多次(不提倡)。它們的作用域是從該說明符出現(xiàn)開始到下一個說明符之前或類體結(jié)束之前結(jié)束。
訪問符說明
private:類的私有成員只能被類的成員函數(shù)、友元函數(shù)、友元類訪問,類外無法訪問他們
protected:類的受保護成員能被類的成員函數(shù)、友元函數(shù)、友元類和派生類成員函數(shù)訪問
public:類的公有成員可以被類的成員函數(shù)、友元函數(shù)、友元類所有能訪問到類的對象的外部程序代碼直接訪問,這部分往往是一些操作(即成員函數(shù))
類的公有成員是類的對外接口
類的功能
類定義了函數(shù)(方法)和數(shù)據(jù)(屬性)的訪問控制屬性
—哪些成員可被外界直接訪問
—哪些成員只能被自己的成員函數(shù)訪問
封裝和信息隱藏技術使類變得很安全
私有數(shù)據(jù)成員只有類自己的成員函數(shù)能訪問
只要確保成員函數(shù)操作的合理合法性,對象就是安全的
提高了程序的可維護性
對象的定義
對象是類的實例。對象是屬于某個已知的類。
定義對象之前,一定要先定義好該對象的類。
定義好的類可以作為新的數(shù)據(jù)類型來使用
聲明的語法:類的名稱 對象的名稱;
例如:
構(gòu)造函數(shù)
對于對象的初始化,采用構(gòu)造函數(shù)(constructor)。編寫一個或一組構(gòu)造函數(shù)。構(gòu)造函數(shù)是特殊的成員函數(shù)
構(gòu)造函數(shù)的功能:為對象分配空間;對數(shù)據(jù)成員賦初值;請求其他資源。
如何聲明構(gòu)造函數(shù):
—函數(shù)名和類名完全相同
—不能定義構(gòu)造函數(shù)的類型(返回類型),也不能使用void
—構(gòu)造函數(shù)應聲明為公有函數(shù),但它不能像其他成員函數(shù)那樣被顯式地調(diào)用
—構(gòu)造函數(shù)可以有任意類型和任意個數(shù)的參數(shù),一個類可以有多個構(gòu)造函數(shù)(重載)
創(chuàng)建類的對象時,自動調(diào)用類的構(gòu)造函數(shù)
創(chuàng)建一個對象時只調(diào)用一個構(gòu)造函數(shù)(根據(jù)參數(shù)列表)且只在創(chuàng)建時調(diào)用一次
構(gòu)造函數(shù)的種類
普通構(gòu)造函數(shù):有兩個或兩個以上參數(shù)的構(gòu)造函數(shù)
默認構(gòu)造函數(shù)
復制(拷貝)構(gòu)造函數(shù)
類型轉(zhuǎn)換構(gòu)造函數(shù)
重載構(gòu)造函數(shù)
在一個類需要接受不同的初始化值時,就需要編寫多個構(gòu)造函數(shù), 他們之間構(gòu)成重載關系。
示例:
class Student{ private:char m_No[4],m_Name[21];int m_Age,m_Score[5]; public:Student(); //默認構(gòu)造函數(shù)Student(char *name,int age,int score[5]); //重載構(gòu)造函數(shù) };默認構(gòu)造函數(shù)
-
哪種構(gòu)造函數(shù)是默認構(gòu)造函數(shù)?
沒有參數(shù)或者所有的參數(shù)都有默認值的構(gòu)造函數(shù)。
-
類里一定會有默認構(gòu)造函數(shù)嗎?
如果類中沒有聲明構(gòu)造函數(shù),編譯器將自動產(chǎn)生一個公共的默認無參數(shù)構(gòu)造函數(shù);如果存在一個構(gòu)造函數(shù)聲明,那么編譯器不會產(chǎn)生一個默認的構(gòu)造函數(shù)
-
默認構(gòu)造函數(shù)何時調(diào)用?
沒有指明初始化對象時,便按默認構(gòu)造函數(shù)來初始化該對象。
例如:Person p1,p2; //使用默認構(gòu)造函數(shù)對p1和p2進行初始化 -
一個類中只能有一個默認構(gòu)造函數(shù)
(如果一個構(gòu)造函數(shù)的所有參數(shù)均有默認值,這時再定義無參數(shù)的默認構(gòu)造函數(shù)無意義,會產(chǎn)生調(diào)用時二義性)
構(gòu)造函數(shù)中使用默認參數(shù)
可以為類的成員函數(shù)指定參數(shù)的默認值,包括構(gòu)造函數(shù)在內(nèi)。
要把默認參數(shù)值放在函數(shù)聲明中,而不應放在函數(shù)定義中
如果一個構(gòu)造函數(shù)的所有參數(shù)均有默認值,這時再定義無參數(shù)的默認構(gòu)造函數(shù)無意義,將產(chǎn)生調(diào)用時二義性。
示例:
class CCube{ public:CCube(double len);CCube(int len=12);//CCube(); private:double m_len; }; CCube::CCube(int len){m_len=len;}拷貝(復制)構(gòu)造函數(shù)
特殊的構(gòu)造函數(shù)
功能:使用一個已經(jīng)存在的對象來初始化一個新的本類的對象
聲明:只有一個參數(shù)并且參數(shù)為該類對象的引用
class 類名{public: 類名(類名 &對象名);};如果類中沒有說明復制構(gòu)造函數(shù),則系統(tǒng)自動生成一個缺省復制構(gòu)造函數(shù),作為該類的公有成員。
淺復制和深復制
淺復制:將對象數(shù)據(jù)成員的值進行簡單的復制
深復制:不僅將對象數(shù)據(jù)成員的值進行復制,而且對指針型數(shù)據(jù)成員生成新空間,然后復制對應的值
實例:
#include <string.h> #include <iostream.h> class Employee { public:Employee(char *n);Employee(Employee &emp);~Employee(); public:char *name; }; Employee::~Employee() {//析構(gòu)函數(shù)delete [] name; } Employee::Employee(char *n) {name = new char[strlen(n)+1];strcpy(name,n); } Employee::Employee(Employee &emp) {int len=strlen(emp.name);name=new char[len+1];strcpy(name,emp.name); } int main() {Employee emp1("zhang");Employee emp2(emp1);//Employee emp2=emp1;cout<<"emp2.name = "<<emp2.name<<endl;return 0; }**注意:對象中包含動態(tài)分配的數(shù)據(jù)成員時,復制構(gòu)造函數(shù)的實現(xiàn)不能只是簡單的賦值。應該先為當前對象的數(shù)據(jù)成員分配新的空間,再將參數(shù)對象中相應的數(shù)據(jù)復制過來。
拷貝構(gòu)造函數(shù)的其他作用
當函數(shù)的形參是類的對象,調(diào)用函數(shù)時,進行形參與實參結(jié)合時使用。這時要在內(nèi)存新建立一個局部對象,并把實參拷貝到新的對象中。理所當然也調(diào)用拷貝構(gòu)造函數(shù)。
當函數(shù)的返回值是類對象,函數(shù)執(zhí)行完成返回調(diào)用者時使用。理由也是要建立一個臨時對象中,再返回調(diào)用者。為什么不直接用要返回的局部對象呢?因為局部對象在離開建立它的函數(shù)時就消亡了,不可能在返回調(diào)用函數(shù)后繼續(xù)生存,所以在處理這種情況時,編譯系統(tǒng)會在調(diào)用函數(shù)的表達式中創(chuàng)建一個無名臨時對象,該臨時對象的生存周期只在函數(shù)調(diào)用處的表達式中。所謂return 對象,實際上是調(diào)用拷貝構(gòu)造函數(shù)把該對象的值拷入臨時對象。如果返回的是變量,處理過程類似,只是不調(diào)用構(gòu)造函數(shù)。
轉(zhuǎn)換構(gòu)造函數(shù)
提供了單個參數(shù)的構(gòu)造函數(shù)
相當于將一個其他類型的數(shù)值或變量轉(zhuǎn)換為自身類型的數(shù)據(jù)。
類的構(gòu)造函數(shù)只有一個參數(shù)是非常危險的,因為編譯器可以使用這種構(gòu)造函數(shù)把參數(shù)的類型隱式轉(zhuǎn)換為類類型
實例:
#include <string.h> #include <iostream.h> class CCube { public:CCube(double len){m_len=len;} public:double m_len; }; int main() {CCube cube=12.4;cube=11; //隱式轉(zhuǎn)換cout<<"cube.m_len = "<<cube.m_len<<endl;return 0; }執(zhí)行結(jié)果: cube.m_len = 11explicit關鍵字
只提供給類的構(gòu)造函數(shù)使用的關鍵字。
編譯器不會把聲明為explicit的構(gòu)造函數(shù)用于隱式轉(zhuǎn)換,它只能在程序代碼中顯示創(chuàng)建對象
#include <string.h> #include <iostream.h> class CCube { public:explicit CCube(double len){m_len=len;} private:double m_len; }; int main() {CCube cube = 12.4;//不允許//cube=11;//不允許return 0; }析構(gòu)函數(shù)
特殊的成員函數(shù)
作用:撤銷對象前做清理工作,一般是釋放對象在生存期間動態(tài)申請的空間
當對象超出其定義范圍時(即釋放該對象時),編譯器自動調(diào)用析構(gòu)函數(shù)。
-對象被定義在函數(shù)體內(nèi),則當這個函數(shù)結(jié)束時,該對象的析構(gòu)函數(shù)被自動調(diào)用。
-對象是使用new運算符動態(tài)創(chuàng)建的,在使用delete運算符釋放它時,delete將會自動調(diào)用析構(gòu)函數(shù)
函數(shù)名和類名相似(前面多了一個字符“~”)
注意:析構(gòu)函數(shù)沒有返回類型,沒有參數(shù),析構(gòu)函數(shù)不能被重載
如果沒有定義析構(gòu)函數(shù),編譯器會自動生成一個默認析構(gòu)函數(shù),其格式如下:
類名::~默認析構(gòu)函數(shù)名( ) { }默認析構(gòu)函數(shù)是一個空函數(shù)。
示例:
class Student { public:Student();~Student(); private:char *m_name; }; Student :: Student() {cout<<"Default constructor called"<<endl;m_name=new char[5];strcpy(m_name,"abc"); } Student ::~Student() {cout<<"Free"<<endl;delete []char; } 《新程序員》:云原生和全面數(shù)字化實踐50位技術專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的复习笔记(二)——C++面向对象设计和使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python学习笔记(五)——函数基础和
- 下一篇: s3c2440移植MQTT