亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C++類和對(duì)象之多態(tài)詳解

 更新時(shí)間:2021年12月22日 10:00:05   作者:燼燼今天學(xué)習(xí)了嗎  
大家好,本篇文章主要講的是C++類和對(duì)象之多態(tài)詳解,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽

多態(tài)基本概念和原理剖析

多態(tài):多態(tài)是C++面向?qū)ο蟮娜筇匦灾?。多態(tài)分為靜態(tài)多態(tài)和動(dòng)態(tài)多態(tài)。
靜態(tài)多態(tài):函數(shù)重載和運(yùn)算符重載屬于靜態(tài)多態(tài),復(fù)用函數(shù)名。
動(dòng)態(tài)多態(tài):派生類和虛函數(shù)實(shí)現(xiàn)運(yùn)行時(shí)多態(tài)。

區(qū)別:
靜態(tài)多態(tài)的函數(shù)地址早綁定,編譯階段確定函數(shù)地址。
動(dòng)態(tài)多態(tài)的函數(shù)地址晚綁定,運(yùn)行階段確定函數(shù)地址。

#include <iostream>
using namespace std;
//動(dòng)態(tài)多態(tài)滿足條件
//1、有繼承關(guān)系
//2、子類重寫(xiě)父類的虛函數(shù) 重寫(xiě)是指返回值 函數(shù)名 參數(shù)完全一樣    重載是指函數(shù)名相同
//動(dòng)態(tài)多態(tài)使用
//父類的指針或引用,指向子類對(duì)象


//當(dāng)子類重寫(xiě)父類的虛函數(shù),子類中的虛函數(shù)表內(nèi)部會(huì)替換成子類的虛函數(shù)地址,將&Animal::speak替換成&Cat::speak

//動(dòng)物類
class Animal {
public:
	//虛函數(shù)
	virtual void speak(){
		cout << "動(dòng)物在說(shuō)話" << endl;
	}
};
//貓類
class Cat :public Animal {
public:
	void speak() {
		cout << "小貓?jiān)谡f(shuō)話" << endl;
	}
};
//狗類
class Dog :public Animal {
public:
	void speak() {
		cout << "小狗在說(shuō)話" << endl;
	}
};

//執(zhí)行說(shuō)話的函數(shù)
//地址早綁定,在編譯階段就確定了函數(shù)的地址
//雖然想讓貓說(shuō)話,但是這里輸出了動(dòng)物在說(shuō)話   因?yàn)榈刂吩缃壎?
//如果想讓貓說(shuō)話,這個(gè)函數(shù)的地址就不能提前綁定,需要在運(yùn)行階段進(jìn)行綁定,也即地址晚綁定
void DoSpeak(Animal &animal) {
	animal.speak();
}
void test01() {
	Cat cat;
	DoSpeak(cat);     //雖然想讓貓說(shuō)話,但是這里輸出了動(dòng)物在說(shuō)話,因?yàn)榈刂吩缃壎?,若父類改為虛函?shù)地址晚綁定,就是貓?jiān)谡f(shuō)話
	Dog dog;
	DoSpeak(dog);
}

void test02() {
	cout << "size of Animal = " << sizeof(Animal) << endl;
}
int main() {
	//test01();
	test02();
	system("pause");
	return 0;
}

多態(tài)案例1 計(jì)算器類

分別使用普通寫(xiě)法和多態(tài)技術(shù),設(shè)計(jì)實(shí)現(xiàn)兩個(gè)操作數(shù)進(jìn)行運(yùn)算的計(jì)算器類。

多態(tài)優(yōu)點(diǎn)
1、代碼組織結(jié)構(gòu)清晰
2、可讀性強(qiáng)
3、便于前期和后期的擴(kuò)展與維護(hù)

#include<iostream>
using namespace std;

//普通寫(xiě)法
class Calculate {
public:
	int GetResult(string oper) {
		if (oper == "+") {
			return num1 + num2;
		}
		else if (oper == "-") {
			return num1 - num2;
		}
		else if (oper == "*") {
			return num1 * num2;
		}
		//如果想擴(kuò)展新的功能,需要修改原碼,在實(shí)際開(kāi)發(fā)中,提倡開(kāi)閉原則:對(duì)擴(kuò)展進(jìn)行開(kāi)發(fā),對(duì)修改進(jìn)行關(guān)閉
	}
	int num1;
	int num2;
};
void test01() {
	//創(chuàng)建計(jì)算器對(duì)象
	Calculate c;
	c.num1 = 10;
	c.num2 = 10;
	cout << c.num1 << " + "<< c.num2 << " = " <<c.GetResult("+") << endl;
	cout << c.num1 << " - "<< c.num2 << " = " <<c.GetResult("-") << endl;
	cout << c.num1 << " * "<< c.num2 << " = " <<c.GetResult("*") << endl;
}


//利用多態(tài)實(shí)現(xiàn)計(jì)算器
//多態(tài)的優(yōu)點(diǎn)
//1、組織結(jié)構(gòu)清晰
//2、可讀性強(qiáng)
//3、對(duì)于前期擴(kuò)展和后期維護(hù)性能高

//實(shí)現(xiàn)計(jì)算器抽象類
class AbstractCalculate {
public:
	virtual int Result() {
		return 0;
	}
	int m_num1;
	int m_num2;
};
//加法計(jì)算器類
class AddCalculate : public AbstractCalculate{
public:
	int Result() {
		return m_num1 + m_num2;
	}
};
//減法計(jì)算器類
class SubCalculate : public AbstractCalculate {
public:
	int Result() {
		return m_num1 - m_num2;
	}
};
//乘法計(jì)算器類
class MulCalculate : public AbstractCalculate {
public:
	int Result() {
		return m_num1 * m_num2;
	}
};
void test02() {
	//多態(tài)使用指針
	//父類指針或者引用指向子類對(duì)象

	//加法運(yùn)算
	AbstractCalculate* p = new AddCalculate;
	p->m_num1 = 100;
	p->m_num2 = 100;
	cout << p->m_num1 << " + " << p->m_num2 << " = " << p->Result() <<endl;
	//用完后釋放新開(kāi)辟的堆區(qū)數(shù)據(jù)
	delete p;

	//減法運(yùn)算
	p = new SubCalculate;
	p->m_num1 = 100;
	p->m_num2 = 100;
	cout << p->m_num1 << " - " << p->m_num2 << " = " << p->Result() << endl;
	delete p;

	//乘法運(yùn)算
	p = new MulCalculate;
	p->m_num1 = 100;
	p->m_num2 = 100;
	cout << p->m_num1 << " * " << p->m_num2 << " = " << p->Result() << endl;
	delete p;
}
int main() {
	//test01();
	test02();
	system("pause");
	return 0;
}

純虛函數(shù)和抽象類

在多態(tài)中,通常父類函數(shù)的虛函數(shù)是無(wú)意義的,主要都是調(diào)用子類重寫(xiě)的內(nèi)容。因此可以將虛函數(shù)改為純虛函數(shù)。當(dāng)類中有了純虛函數(shù),這個(gè)類也稱為抽象類。
.
抽象類特點(diǎn):無(wú)法實(shí)例化對(duì)象;子類必須重新抽象類中的純虛函數(shù),否則也屬于抽象類。

#include<iostream>
using namespace std;
//純虛函數(shù)語(yǔ)法 virtual 返回值 函數(shù)名(參數(shù)列表) = 0;
//當(dāng)類中有了純虛函數(shù),這個(gè)類也稱為抽象類,抽象類不能實(shí)例化對(duì)象,子類必須重寫(xiě)抽象類里的純虛函數(shù),不然子類也屬于抽象類
class Base {
public:
	//純虛函數(shù) 只要有純虛函數(shù)這個(gè)類就是抽象類
	virtual void func() = 0;
};
class Son :public Base {
public:
	void func() {
		cout << "Son類下的func函數(shù)調(diào)用" << endl;
	}
};
void test01() {
	/*抽象類是無(wú)法實(shí)例化對(duì)象的
	Base b;
	new Base;*/
	Son s;
	s.func();
	//多態(tài)方式調(diào)用 父類的指針new一個(gè)子類
	Base* p = new Son;
	p->func();
	delete p;
}

int main() {
	test01();
	system("pause");
	return 0;
}

多態(tài)案例2 制作飲品

利用多態(tài)技術(shù)實(shí)現(xiàn)制作飲品的流程,提供抽象制作飲品基類,提供子類制作咖啡和茶。

這里使用指針多態(tài)而不是引用的原因在于,引用需先實(shí)例化對(duì)象,但是有純虛函數(shù)的抽象類無(wú)法實(shí)例化對(duì)象。

#include<iostream>
using namespace std;
class AbstractDrinking {
public:
	//煮水
	virtual void Boil() = 0;
	//沖泡
	virtual void Brew() = 0;
	//倒入杯中
	virtual void DropInCup() = 0;
	//加入輔料
	virtual void AddSomething() = 0;

	//制作飲品
	void MakeDrink() {
		Boil();
		Brew();
		DropInCup();
		AddSomething();
	}
};

//制作咖啡流程
class Coffee : public AbstractDrinking {
public:
	//煮水
	virtual void Boil() {
		cout << "煮一壺沸水" << endl;
	}
	//沖泡
	virtual void Brew() {
		cout << "沖泡咖啡粉" << endl;
	}
	//倒入杯中
	virtual void DropInCup() {
		cout << "將咖啡倒入杯中" << endl;
	}
	//加入輔料
	virtual void AddSomething() {
		cout << "將牛奶和白糖加入咖啡中" << endl;
	}
};


//制作茶水流程
class Tea : public AbstractDrinking {
public:
	//煮水
	virtual void Boil() {
		cout << "煮一壺沸水" << endl;
	}
	//沖泡
	virtual void Brew() {
		cout << "沖泡西湖龍井" << endl;
	}
	//倒入杯中
	virtual void DropInCup() {
		cout << "將茶水倒入杯中" << endl;
	}
	//加入輔料
	virtual void AddSomething() {
		cout << "將枸杞加入茶水中" << endl;
	}
};

//制作飲品函數(shù)
void DoWork(AbstractDrinking *p) {   //這里相當(dāng)于 AbstractDrinking *p = new Coffee;
	                                //若這里不使用指針,改為引用,test01的函數(shù)就不能使用
	                               //因?yàn)橐檬窍葘?shí)例化對(duì)象再調(diào)用對(duì)象,抽象類無(wú)法實(shí)例化對(duì)象
	p->MakeDrink();
	delete p;  //防止內(nèi)存泄露,使用后記得釋放內(nèi)存
}
void test01() {
	//想喝一杯咖啡
	DoWork(new Coffee);
	cout << "-----------------------------------" << endl;
	//想喝一杯西湖龍井茶
	DoWork(new Tea);
}

int main() {
	test01();
	system("pause");
	return 0;
}

虛析構(gòu)和純虛析構(gòu)

使用多態(tài)技術(shù)時(shí),如果有子類開(kāi)辟到堆區(qū),那么父類指針在釋放時(shí)無(wú)法調(diào)用到子類的析構(gòu)代碼。解決該問(wèn)題的方法是將父類中的析構(gòu)函數(shù)改為虛析構(gòu)或者純虛析構(gòu)。

虛析構(gòu)和純虛析構(gòu)共性
1、可以解決父類指針釋放子類對(duì)象
2、都需要有具體的函數(shù)實(shí)現(xiàn)
虛析構(gòu)和純虛析構(gòu)區(qū)別
如果是純虛析構(gòu),該類屬于抽象類,無(wú)法實(shí)例化對(duì)象。

#include<iostream>
#include<string>
using namespace std;
//動(dòng)物類
class Animal {
public:
	Animal() {
		cout << "這是Animal的構(gòu)造函數(shù)調(diào)用" << endl;
	}
	//純虛函數(shù)
	virtual void Speak() = 0;

	//為了走子類的虛構(gòu)函數(shù),需要將父類的虛構(gòu)函數(shù)改為虛析構(gòu)
	/*virtual ~Animal() {
		cout << "這是Animal的析構(gòu)函數(shù)調(diào)用" << endl;
	}*/
	//純虛析構(gòu)函數(shù)  父類的堆區(qū)可能也被開(kāi)辟需要釋放,因此父類的析構(gòu)也必須需要聲明,也需要實(shí)現(xiàn)
	//有純虛析構(gòu)后這個(gè)類也屬于抽象類,無(wú)法實(shí)例化對(duì)象
	virtual ~Animal() = 0;
};
Animal:: ~Animal() {
	cout << "這是Animal類的寫(xiě)在外部的純虛析構(gòu)函數(shù)調(diào)用" << endl;
}

//貓類
class Cat : public Animal{
public:
	//Cat類的構(gòu)造函數(shù)
	Cat(string name) {
		cout << "這是Cat類的構(gòu)造函數(shù)" << endl;
		m_name = new string(name);
	}
	void Speak() {
		cout << *m_name<<"小貓的叫聲" << endl;
	}
	~Cat() {
		if (m_name != NULL) {
			//父類指針在析構(gòu)的時(shí)候,不會(huì)調(diào)用子類中的析構(gòu)函數(shù),導(dǎo)致子類中有堆區(qū)開(kāi)辟的數(shù)據(jù)沒(méi)有被釋放干凈導(dǎo)致內(nèi)存泄露
			cout << "這是Cat類的析構(gòu)函數(shù)" << endl;
			delete m_name;
			m_name = NULL;
		}
	}
	string *m_name;
	
};

void test01() {
	Animal* p = new Cat("Tom");             //如果子類中沒(méi)有堆區(qū)數(shù)據(jù),可以不寫(xiě)虛析構(gòu)或純虛析構(gòu)函數(shù)
	p->Speak();
	delete p;     //堆區(qū)開(kāi)辟以后,釋放指針
}

int main() {
	test01();
	system("pause");
	return 0;
}

多態(tài)案例3 電腦組裝

電腦主要部件為CPU,顯卡和內(nèi)存條。將每個(gè)零件封裝出抽象基類,并提供不同的廠商生產(chǎn)不同的零件。創(chuàng)建電腦類提供讓電腦工作的函數(shù),并且調(diào)用每個(gè)零件工作的接口。測(cè)試時(shí)組裝三臺(tái)不同的電腦進(jìn)行工作。

#include<iostream>
using namespace std;
//每個(gè)零件都封裝出抽象的基類
//CPU類
class Cpu {
public:
	//抽象的計(jì)算函數(shù)
	virtual void Calculate() = 0;
	//virtual ~Cpu() = 0; 
};
//Cpu::~Cpu() {
//	cout << "Cpu類寫(xiě)在外部的純虛析構(gòu)函數(shù)調(diào)用" << endl;
//}
//顯卡類
class VideoCard {
public:
	//抽象的顯示函數(shù)
	virtual void Display() = 0;
};
//內(nèi)存條類
class Memory {
public:
	//抽象的存儲(chǔ)函數(shù)
	virtual void Storage() = 0;
};


//電腦類
class Computer {
public:
	Computer(Cpu* cpu, VideoCard* videocard, Memory* memory) {
		m_cpu = cpu;
		m_videocard = videocard;
		m_memory = memory;
	}
	//工作函數(shù):讓零件調(diào)用起來(lái)的工作接口  父類指針調(diào)用接口時(shí)就已經(jīng)是多態(tài)技術(shù)了
	void DoWork() {
		//Cpu進(jìn)行計(jì)算操作
		m_cpu->Calculate();
		//顯卡進(jìn)行顯示操作
		m_videocard->Display();
		//內(nèi)存條進(jìn)行存儲(chǔ)操作
		m_memory->Storage();
	}
	//提供析構(gòu)函數(shù)釋放電腦的三個(gè)零件
	~Computer() {
		if (m_cpu != NULL) {
			delete m_cpu;
			m_cpu = NULL;
		}
		if (m_videocard != NULL) {
			delete m_videocard;
			m_videocard = NULL;
		}
		if (m_memory != NULL) {
			delete m_memory;
			m_memory = NULL;
		}
	}
private:
	Cpu *m_cpu;
	VideoCard *m_videocard;
	Memory *m_memory;
};


//具體廠商///
//因特爾廠商
class IntelCpu :public Cpu{
public:
	//子類重寫(xiě)父類的虛函數(shù)
	virtual void Calculate() {
		cout << "Intel的Cpu開(kāi)始計(jì)算了!" << endl;
	}
	/*~IntelCpu() {
		cout << "這是子類IntelCpu的析構(gòu)函數(shù)調(diào)用" << endl;
	}*/
};
class IntelVideoCard :public VideoCard {
public:
	//子類重寫(xiě)父類的虛函數(shù)
	virtual void Display() {
		cout << "Intel的顯卡開(kāi)始顯示屏幕了!" << endl;
	}
};
class IntelMemory :public Memory {
public:
	//子類重寫(xiě)父類的虛函數(shù)
	virtual void Storage() {
		cout << "Intel的內(nèi)存條開(kāi)始存儲(chǔ)數(shù)據(jù)了!" << endl;
	}
};

//Lenovo廠商
class LenovoCpu :public Cpu {
public:
	//子類重寫(xiě)父類的虛函數(shù)
	virtual void Calculate() {
		cout << "Lenovo的Cpu開(kāi)始計(jì)算了!" << endl;
	}
};
class LenovoVideoCard :public VideoCard {
public:
	//子類重寫(xiě)父類的虛函數(shù)
	virtual void Display() {
		cout << "Lenovo的顯卡開(kāi)始顯示屏幕了!" << endl;
	}
};
class LenovoMemory :public Memory {
public:
	//子類重寫(xiě)父類的虛函數(shù)
	virtual void Storage() {
		cout << "Lenovo的內(nèi)存條開(kāi)始存儲(chǔ)數(shù)據(jù)了!" << endl;
	}
};


//開(kāi)始測(cè)試,組裝不同的電腦
void test01() {
	//第一臺(tái)電腦的零件
	//父類指針指向了子類對(duì)象,利用了多態(tài)技術(shù)
	Cpu* intelcpu = new IntelCpu;
	VideoCard* intelvideocard = new IntelVideoCard;
	Memory* intelmemory = new IntelMemory;
	//創(chuàng)建第一臺(tái)電腦
	cout << "組裝好的第一臺(tái)電腦配置如下:" << endl;
	Computer* computer1 = new Computer(intelcpu,intelvideocard,intelmemory);
	computer1->DoWork();
	delete computer1;

	//創(chuàng)建第二臺(tái)電腦
	cout << "組裝好的第二臺(tái)電腦配置如下:" << endl;
	Computer* computer2 = new Computer(new LenovoCpu, new LenovoVideoCard, new LenovoMemory);
	computer2->DoWork();
	delete computer2;

	//創(chuàng)建第三臺(tái)電腦
	cout << "組裝好的第三臺(tái)電腦配置如下:" << endl;
	Computer* computer3 = new Computer(new LenovoCpu, new IntelVideoCard, new LenovoMemory);
	computer3->DoWork();
	delete computer3;

}

int main() {
	test01();
	system("pause");
	return 0;
}

到此這篇關(guān)于C++類和對(duì)象之多態(tài)詳解的文章就介紹到這了,更多相關(guān)C++多態(tài)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

  • C++實(shí)現(xiàn)重載矩陣的部分運(yùn)算符

    C++實(shí)現(xiàn)重載矩陣的部分運(yùn)算符

    這篇文章主要為大家詳細(xì)介紹了如何利用C++實(shí)現(xiàn)重載矩陣的部分運(yùn)算符,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C++有一定幫助,需要的可以參考一下
    2022-10-10
  • 詳解C/C++實(shí)現(xiàn)各種字符轉(zhuǎn)換方法合集

    詳解C/C++實(shí)現(xiàn)各種字符轉(zhuǎn)換方法合集

    這篇文章主要為大家詳細(xì)介紹了C/C++中實(shí)現(xiàn)各種字符轉(zhuǎn)換的方法,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C++具有一定借鑒價(jià)值,需要的可以參考一下
    2022-09-09
  • C++字符串類的封裝你真的了解嗎

    C++字符串類的封裝你真的了解嗎

    這篇文章主要為大家詳細(xì)介紹了C++字符串類的封裝,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02
  • C語(yǔ)言中堆空間的生成與釋放詳解

    C語(yǔ)言中堆空間的生成與釋放詳解

    以下是對(duì)C語(yǔ)言中堆空間的生成與釋放進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過(guò)來(lái)參考下
    2013-08-08
  • c語(yǔ)言 sscanf,scanf,fscanf正則表達(dá)式用法

    c語(yǔ)言 sscanf,scanf,fscanf正則表達(dá)式用法

    每種語(yǔ)言都對(duì)正則表達(dá)式有著不同程度的支持,在C語(yǔ)言中,有輸入功能的這三個(gè)函數(shù)對(duì)正則表達(dá)式的支持并不強(qiáng)大,但是我們還是有必要了解一下
    2018-04-04
  • C++之異常處理詳解

    C++之異常處理詳解

    C++中處理異常的過(guò)程是這樣的:在執(zhí)行程序發(fā)生異常,可以不在本函數(shù)中處理,而是拋出一個(gè)錯(cuò)誤信息,把它傳遞給上一級(jí)的函數(shù)來(lái)解決,上一級(jí)解決不了,再傳給其上一級(jí),由其上一級(jí)處理
    2013-08-08
  • C++字符數(shù)組、字符數(shù)組指針和string類

    C++字符數(shù)組、字符數(shù)組指針和string類

    這篇文章主要介紹了C++字符數(shù)組、字符數(shù)組指針和string類,string是一個(gè)類而不是基本數(shù)據(jù)類型,數(shù)組不含有處理函數(shù),下面更多詳細(xì)內(nèi)容,需要的小伙伴可以參考下面文章
    2022-03-03
  • C語(yǔ)言中邏輯運(yùn)算符與條件運(yùn)算符的學(xué)習(xí)教程

    C語(yǔ)言中邏輯運(yùn)算符與條件運(yùn)算符的學(xué)習(xí)教程

    這篇文章主要介紹了C語(yǔ)言中邏輯運(yùn)算符與條件運(yùn)算符的學(xué)習(xí)教程,條件運(yùn)算符問(wèn)號(hào)即三目運(yùn)算符使用起來(lái)十分方便,需要的朋友可以參考下
    2016-04-04
  • C語(yǔ)言函數(shù)棧幀的創(chuàng)建與銷毀詳解

    C語(yǔ)言函數(shù)棧幀的創(chuàng)建與銷毀詳解

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言函數(shù)棧幀的創(chuàng)建與銷毀,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02
  • 最新評(píng)論