C++之普通成員函數(shù)、虛函數(shù)以及純虛函數(shù)的區(qū)別與用法要點(diǎn)
普通成員函數(shù)是靜態(tài)編譯的,沒有運(yùn)行時(shí)多態(tài),只會(huì)根據(jù)指針或引用的“字面值”類對(duì)象,調(diào)用自己的普通函數(shù);虛函數(shù)為了重載和多態(tài)的需要,在基類中定義的,即便定義為空;純虛函數(shù)是在基類中聲明的虛函數(shù),它可以再基類中有定義,且派生類必須定義自己的實(shí)現(xiàn)方法。
假設(shè)我們有三個(gè)類Person、Teacher、Student它們之間的關(guān)系如下:
類的關(guān)系圖
普通成員函數(shù)
【Demo1】
根據(jù)這個(gè)類圖,我們有下面的代碼實(shí)現(xiàn)
#ifndef __OBJEDT_H__ #define __OBJEDT_H__ #include <string> #include <iostream> class Person { public: Person(const string& name, int age) : m_name(name), m_age(age) { } void ShowInfo() { cout << "姓名:" << m_name << endl; cout << "年齡:" << m_age << endl; } protected: string m_name; //姓名 int m_age; //年齡 }; class Teacher : public Person { public: Teacher(const string& name, int age, const string& title) : Person(name, age), m_title(title) { } void ShowInfo() { cout << "姓名:" << m_name << endl; cout << "年齡:" << m_age << endl; cout << "職稱:" << m_title << endl; } private: string m_title; //職稱 }; class Student : public Person { public: Student(const string& name, int age, int studyId) : Person(name, age), m_studyId(studyId) { } void ShowInfo() { cout << "姓名:" << m_name << endl; cout << "年齡:" << m_age << endl; cout << "學(xué)號(hào):" << m_studyId << endl; } private: int m_studyId; //學(xué)號(hào) }; #endif //__OBJEDT_H__
測(cè)試代碼:
void test() { Person* pPerson = new Person("張三", 22); Teacher* pTeacher = new Teacher("李四", 35, "副教授"); Student* pStudent = new Student("王五", 18, 20151653); pPerson->ShowInfo(); cout << endl; pTeacher->ShowInfo(); cout << endl; pStudent->ShowInfo(); cout << endl; delete pPerson; delete pTeacher; delete pStudent; }
結(jié)果:
姓名:張三
年齡:22
姓名:李四
年齡:35
職稱:副教授
姓名:王五
年齡:18
學(xué)號(hào):20151653
說(shuō)明:
這里的ShowInfo就是一個(gè)普通的函數(shù)。pPerson、pTeacher和pStudent三個(gè)對(duì)象調(diào)用ShowInfo分別展示自己的信息。
我們知道:父類的指針是可以指向子類的對(duì)象的。我們把上面的測(cè)試代碼稍微改一下:
【Demo2】
void test() { Person* pPerson = new Person("張三", 22); Person* pTeacher = new Teacher("李四", 35, "副教授"); Person* pStudent = new Student("王五", 18, 20151653); pPerson->ShowInfo(); cout << endl; pTeacher->ShowInfo(); cout << endl; pStudent->ShowInfo(); cout << endl; delete pPerson; delete pTeacher; delete pStudent; }
結(jié)果:
姓名:張三
年齡:22
姓名:李四
年齡:35
姓名:王五
年齡:18
這時(shí),pTeacher和pStudent只輸出了姓名和年齡,并沒有輸出子類所具有的特性(職稱和學(xué)號(hào))。這應(yīng)該不是你期望的結(jié)果,你可能期望pTeacher和pStudent輸出老師和學(xué)生的完整信息,這時(shí)就需要用虛函數(shù)。
虛函數(shù)
我們把Person中的ShowInfo成員改成虛函數(shù)(在前面加上virtual),代碼如下:
【Demo3】
class Person { public: Person(const string& name, int age) : m_name(name), m_age(age) { } virtual void ShowInfo() { cout << "姓名:" << m_name << endl; cout << "年齡:" << m_age << endl; } protected: string m_name; //姓名 int m_age; //年齡 };
在執(zhí)行上面【Demo2】中的測(cè)試代碼,得到我們想到的結(jié)果:
姓名:張三
年齡:22
姓名:李四
年齡:35
職稱:副教授
姓名:王五
年齡:18
學(xué)號(hào):20151653
虛函數(shù)用法要點(diǎn):
- 虛函數(shù)的聲明方式:virtual RETURN_TYPE functionName(ARGS 參數(shù)列表);
- 虛函數(shù)作用:現(xiàn)實(shí)C++中的多態(tài),進(jìn)行動(dòng)態(tài)綁定(父類指針可指向子類的對(duì)象),直到運(yùn)行時(shí)才知道要調(diào)用哪個(gè)版本(哪個(gè)類定義)的函數(shù);
- 我們必要對(duì)虛函數(shù)進(jìn)行定義;
- 一旦父類的成員函數(shù)聲明virtual,其子類的函數(shù)不管有沒有聲明為virtual,都是虛函數(shù);
- 如果虛函數(shù)使用默認(rèn)實(shí)參,父類和子類定義的默認(rèn)實(shí)參最好一致。
【Demo4】:針對(duì)第4點(diǎn)說(shuō)明:
class Person { public: Person(const string& name, int age) : m_name(name), m_age(age) { } virtual void ShowInfo() { cout << "姓名:" << m_name << endl; cout << "年齡:" << m_age << endl; } string GetName(); //正確,普通函數(shù)如果不被使用,可以只有聲明沒有定義 virtual int GetAge(); //錯(cuò)誤,虛函數(shù)必須要有定義,即使是一個(gè)空實(shí)現(xiàn),因?yàn)榫幾g器無(wú)法確定會(huì)使用哪個(gè)函數(shù) protected: string m_name; //姓名 int m_age; //年齡 };
【Demo5】:針對(duì)第5點(diǎn)進(jìn)行說(shuō)明:
設(shè)計(jì)我們的類如下定義。
class Person { public: virtual void SetAge(int age = 0) { m_age = age; } //... 省略 }; class Teacher : public Person { public: virtual void SetAge(int age = 1) { m_age = age; } //... 省略 }; class Student : public Person { public: virtual void SetAge(int age = 2) { m_age = age; } //... 省略 };
測(cè)試1:
void test() { Person* pPerson = new Person("張三", 22); Teacher* pTeacher = new Teacher("李四", 35, "副教授"); Student* pStudent = new Student("王五", 18, 20151653); pPerson->SetAge(); pTeacher->SetAge(); pStudent->SetAge(); pPerson->ShowInfo(); cout << endl; pTeacher->ShowInfo(); cout << endl; pStudent->ShowInfo(); cout << endl; delete pPerson; delete pTeacher; delete pStudent; }
結(jié)果:
姓名:張三
年齡:0
姓名:李四
年齡:1
職稱:副教授
姓名:王五
年齡:2
學(xué)號(hào):20151653
測(cè)試2:
void test() { Person* pPerson = new Person("張三", 22); Person* pTeacher = new Teacher("李四", 35, "副教授"); Person* pStudent = new Student("王五", 18, 20151653); pPerson->SetAge(); pTeacher->SetAge(); pStudent->SetAge(); pPerson->ShowInfo(); cout << endl; pTeacher->ShowInfo(); cout << endl; pStudent->ShowInfo(); cout << endl; delete pPerson; delete pTeacher; delete pStudent; }
結(jié)果:
姓名:張三
年齡:0
姓名:李四
年齡:0
職稱:副教授
姓名:王五
年齡:0
學(xué)號(hào):20151653
純虛函數(shù)
在上面的例子中,我們假設(shè)所有的人都要工作,但不同的人工作的方式不同。于是我們就要強(qiáng)制要求繼承自Person的子類都要有工作的方法,這就需要純虛函數(shù)。定義如下:
【Demo6】
class Person { public: //... 省略 virtual void DoWork() = 0; //... 省略 };
但此時(shí)我們編譯
Person* pPerson = new Person("張三", 22);
這句話時(shí)會(huì)報(bào)錯(cuò):error C2259: ‘Person' : cannot instantiate abstract class
這是因?yàn)槲覀儾]有為Person實(shí)現(xiàn)DoWork方法,而包含純虛函數(shù)的類是一個(gè)抽象的類,抽象類不能被實(shí)例化。
于是我們?cè)谧宇愔袑?duì)它實(shí)現(xiàn)如下:
【Demo7】
class Teacher : public Person { public: //... 省略 virtual void DoWork() { cout << "教書..." << endl; } //... 省略 }; class Student : public Person { public: //... 省略 virtual void DoWork() { cout << "學(xué)習(xí)..." << endl; } //... 省略 };
沒用DoWork方法:
void test() { Person* pTeacher = new Teacher("李四", 35, "副教授"); Person* pStudent = new Student("王五", 18, 20151653); pTeacher->DoWork(); cout << endl; pStudent->DoWork(); cout << endl; delete pTeacher; delete pStudent; }
結(jié)果:
教書…
學(xué)習(xí)…
純虛函數(shù)用法要點(diǎn):
- 純虛函數(shù)的聲明方式:virtual RETURN_TYPE functionName(ARGS 參數(shù)列表) = 0;
- 含有純虛函數(shù)的類是一個(gè)抽象的類,抽象類不能被實(shí)例化。
- 包含純虛函數(shù)的抽象類常用來(lái)當(dāng)作對(duì)外的接口,說(shuō)明這個(gè)類有什么功能,而沒有具體的實(shí)現(xiàn),基體的實(shí)現(xiàn)交由子類完成。
通過(guò)以上對(duì)普通成員函數(shù)、虛函數(shù)以及純虛函數(shù)的介紹,希望可以對(duì)大家有所幫助。
上一篇:Linux下C語(yǔ)言修改進(jìn)程名稱的方法
欄 目:C語(yǔ)言
下一篇:C++實(shí)現(xiàn)Linux下彈出U盤的方法
本文標(biāo)題:C++之普通成員函數(shù)、虛函數(shù)以及純虛函數(shù)的區(qū)別與用法要點(diǎn)
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/2955.html
您可能感興趣的文章
- 04-02c語(yǔ)言沒有round函數(shù) round c語(yǔ)言
- 01-10深入理解C++中常見的關(guān)鍵字含義
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10APUE筆記之:進(jìn)程環(huán)境詳解
- 01-10c++中inline的用法分析
- 01-10用C++實(shí)現(xiàn)DBSCAN聚類算法
- 01-10全排列算法的非遞歸實(shí)現(xiàn)與遞歸實(shí)現(xiàn)的方法(C++)
- 01-10C++大數(shù)模板(推薦)
- 01-10淺談C/C++中的static與extern關(guān)鍵字的使用詳解
- 01-10深入C/C++浮點(diǎn)數(shù)在內(nèi)存中的存儲(chǔ)方式詳解


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 04-02jquery與jsp,用jquery
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10delphi制作wav文件的方法
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改