#include<iostream>
using namespace std;
//多態(tài)
//動(dòng)物類
class Animal
{
public:
?? ?//Speak函數(shù)就是虛函數(shù)
?? ?//函數(shù)前面加上virtual關(guān)鍵字,變成虛函數(shù),那么編譯器在編譯的時(shí)候就不能確定函數(shù)調(diào)用了。
?? ?virtual void speak()
?? ?{
?? ??? ?cout << "動(dòng)物在說話" << endl;
?? ?}
};
//貓類
class Cat :public Animal
{
public:
?? ?//重寫 函數(shù)返回值類型? 函數(shù)名? 參數(shù)列表? 完全相同
?? ?void speak()
?? ?{
?? ??? ?cout << "小貓?jiān)谡f話" << endl;
?? ?}
};
//狗類
class Dog :public Animal
{
public:
?? ?void speak()
?? ?{
?? ??? ?cout << "小狗在說話" << endl;
?? ?}
};
//我們希望傳入什么對(duì)象,那么就調(diào)用什么對(duì)象的函數(shù)
//如果函數(shù)地址在編譯階段就能確定,那么靜態(tài)聯(lián)編
//如果函數(shù)地址在運(yùn)行階段才能確定,就是動(dòng)態(tài)聯(lián)編
//執(zhí)行說話的函數(shù)
//地址早綁定? 在編譯階段確定函數(shù)地址
//如果想執(zhí)行讓貓說話,那么這個(gè)函數(shù)地址就不能提前綁定,需要在運(yùn)行階段進(jìn)行綁定,地址晚綁定
//動(dòng)態(tài)多態(tài)滿足條件
//1.有繼承關(guān)系
//2.子類重寫父類的虛函數(shù)
//動(dòng)態(tài)多態(tài)使用
//父類的指針或者引用? 執(zhí)向子類對(duì)象
void DoSpeak(Animal & animal)
{
?? ?animal.speak();
}
//
//多態(tài)滿足條件:
//1、有繼承關(guān)系
//2、子類重寫父類中的虛函數(shù)
//多態(tài)使用:
//父類指針或引用指向子類對(duì)象
void test01()
{
?? ?Cat cat;
?? ?DoSpeak(cat);
?? ?Dog dog;
?? ?DoSpeak(dog);
}
int main() {
?? ?test01();
?? ?system("pause");
?? ?return 0;
}
總結(jié):
多態(tài)滿足條件
* 有繼承關(guān)系
* 子類重寫父類中的虛函數(shù)
多態(tài)使用條件
* 父類指針或引用指向子類對(duì)象
重寫:函數(shù)返回值類型? 函數(shù)名 參數(shù)列表 完全一致稱為重寫
#include<iostream>
using namespace std;
//純虛函數(shù)和抽象類
class Base
{
public:
?? ?//純虛函數(shù)
?? ?//類中只要有一個(gè)純虛函數(shù)就稱為抽象類
?? ?//抽象類特點(diǎn):
?? ?//1.無法實(shí)例化對(duì)象
?? ?//2.抽象類的子類 必須重寫父類中的純虛函數(shù),否則也屬于抽象類
?? ?virtual void func() = 0;
};
class Son :public Base
{
public:
?? ?virtual void func()
?? ?{
?? ??? ?cout << "func調(diào)用" << endl;
?? ?};
};
void test01()
{
?? ?//Base b;?? //抽象類無法實(shí)例化對(duì)象
?? ?//new Base; //抽象類無法實(shí)例化對(duì)象
?? ?//Son s;//子類必須重寫父類中的純虛函數(shù),否則無法實(shí)例化對(duì)象
?? ?Base * base = new Son;
?? ?base->func();
?? ?delete base;//記得銷毀
}
int main() {
?? ?test01();
?? ?system("pause");
?? ?return 0;
}
#include<iostream>
using namespace std;
#include<string>
//虛析構(gòu)和純虛析構(gòu)
class Animal
{
public:
?? ?Animal()
?? ?{
?? ??? ?cout << "Animal 構(gòu)造函數(shù)調(diào)用!" << endl;
?? ?}
?? ?//純虛函數(shù)
?? ?virtual void Speak() = 0;
?? ?//利用虛析構(gòu)可以解決 父類指針釋放子類對(duì)象時(shí)不干凈的問題
?? ?//析構(gòu)函數(shù)加上virtual關(guān)鍵字,變成虛析構(gòu)函數(shù)
?? ?//virtual ~Animal()
?? ?//{
?? ?//?? ?cout << "Animal虛析構(gòu)函數(shù)調(diào)用!" << endl;
?? ?//}
?? ?//純虛析構(gòu)? 需要聲明也需要實(shí)現(xiàn)
?? ?//有了純虛析構(gòu) 之后,這個(gè)類也屬于抽象類,無法實(shí)例化對(duì)象
?? ?virtual ~Animal() = 0;
};
Animal::~Animal()
{
?? ?cout << "Animal 純虛析構(gòu)函數(shù)調(diào)用!" << endl;
}
//和包含普通純虛函數(shù)的類一樣,包含了純虛析構(gòu)函數(shù)的類也是一個(gè)抽象類。不能夠被實(shí)例化。
class Cat : public Animal
{
public:
?? ?Cat(string name)
?? ?{
?? ??? ?cout << "Cat構(gòu)造函數(shù)調(diào)用!" << endl;
?? ??? ?m_Name = new string(name);
?? ?}
?? ?virtual void Speak()
?? ?{
?? ??? ?cout << *m_Name <<? "小貓?jiān)谡f話!" << endl;
?? ?}
?? ?~Cat()
?? ?{
?? ??? ?cout << "Cat析構(gòu)函數(shù)調(diào)用!" << endl;
?? ??? ?if (this->m_Name != NULL)
?? ??? ?{
?? ??? ??? ?delete m_Name;
?? ??? ??? ?m_Name = NULL;
?? ??? ?}
?? ?}
public:
?? ?string * m_Name;
};
void test01()
{
?? ?Animal * animal = new Cat("Tom");
?? ?animal->Speak();
?? ?//通過父類指針去釋放,會(huì)導(dǎo)致子類對(duì)象可能清理不干凈,造成內(nèi)存泄漏
?? ?//怎么解決?給基類增加一個(gè)虛析構(gòu)函數(shù)
?? ?//虛析構(gòu)函數(shù)就是用來解決通過父類指針釋放子類對(duì)象
?? ?//父類指針在析構(gòu)時(shí)候 不會(huì)調(diào)用子類中析構(gòu)函數(shù),導(dǎo)致子類如果有堆區(qū)屬性,出現(xiàn)內(nèi)存泄露
?? ?delete animal;
}
int main() {
?? ?test01();
?? ?system("pause");
?? ?return 0;
}
總結(jié):
??? ?1. 虛析構(gòu)或純虛析構(gòu)就是用來解決通過父類指針釋放子類對(duì)象
??? ?2. 如果子類中沒有堆區(qū)數(shù)據(jù),可以不寫為虛析構(gòu)或純虛析構(gòu)文章來源:http://www.zghlxwxcb.cn/news/detail-830424.html
??? ?3. 擁有純虛析構(gòu)函數(shù)的類也屬于抽象類文章來源地址http://www.zghlxwxcb.cn/news/detail-830424.html
到了這里,關(guān)于C++類和對(duì)象-多態(tài)->多態(tài)的基本語法、多態(tài)的原理剖析、純虛函數(shù)和抽象類、虛析構(gòu)和純虛析構(gòu)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!