IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【 第9节 C++虚函数和多态】 -> 正文阅读

[C++知识库]【 第9节 C++虚函数和多态】

第9节 C++虚函数和多态

虚函数和虚函数表

什么是虚函数?用virtual修饰的成员函数叫做虚函数

虚函数对于类的影响

  • 增加一个指针的内存,32位4个字节,6位就是8个字节

虚函数表(了解一下):就是一个指针存储所有虚函数的首地址

#include<iostream>
using namespace std;
class MM
{
public:
	virtual void print()
	{
		cout << "虚函数1" << endl;
	}
	virtual void print2()
	{
		cout << "虚函数2" << endl;
	}
	virtual void print3();

protected:

};
void MM::print3()
{
	cout << "虚函数3" << endl;
}
class A
{
	int age;
};

void testVirtual()
{
	//c语言不允许存在空的结构体
	cout << sizeof(MM) << endl;//空的类或者结构体 占用1字节
	cout << sizeof(A) << endl;
	MM mm;
	//虚函数表
	int** vptr = (int**)&mm;
	typedef void(*PF)();
	PF func = (PF)vptr[0][0];
	func();//调用第一个虚函数
	func = (PF)vptr[0][1];
	func();//调用第二个虚函数
}



int main()
{

	testVirtual();
	return 0;
}

虚函数和多态

多态定义:同一种行为(调用)导致的不同的结果

多态的必要性原则

  • 必须父类存在虚函数
  • 子类必须采用public继承
  • 必须存在指针的引用(使用)
#include<iostream>
using namespace std;
class Man
{
public:
	void WC1()
	{
		cout << "狗妈妈走路" << endl;
	}
	virtual void WC2()//父类必须要有virtual
	{
		cout << "小狗走路" << endl;
	}
protected:
};
class Woman:public Man
{
public:
	void WC1()
	{
		cout << "猫猫走路" << endl;
	}
	void WC2()
	{
		cout << "猫猫走路" << endl;
	}
protected:
};

void testVirtual()
{
	//正常访问不存在多态
	cout << "正常访问,就近原则" << endl;
	Man pm;
	pm.WC1();
	pm.WC2();
	Woman woman;
	woman.WC1();
	woman.WC2();
	cout << "指针访问,正常赋值" << endl;
	Man* pm1 = new Man;
	pm1->WC1();
	pm1->WC2();

	Woman* pw = new Woman;
	pw->WC1();
	pw->WC2();
	cout << "指针非正常赋值:子类对象初始化父类指针" << endl;
	Man* parent = new Woman;
	//有virtual看对象类型,没有virtual 看指针
	parent->WC1();//不是虚函数
	parent->WC2();//是虚函数
	parent = new Man;
	parent->WC2();

}

class Shape
{
public:
	virtual void Draw()
	{
		cout << "绘制过程" << endl;
	}
protected:
};
class Rect :public Shape
{
public:
	virtual void Draw()
	{
		cout << "画矩形" << endl;
	}
protected:
};
class Circle :public Shape
{
public:
	virtual void Draw()
	{
		cout << "画圆" << endl;
	}
protected:
};
//统一接口功能
void printInfo(Man* parent)
{
	parent->WC2();
}
class Triangle :public Shape
{
public:
	void Draw()
	{
		cout << "绘制三角形" <<endl;
	}
};
class Elliptical :public Shape
{
public:
	void Draw()
	{
		cout << "绘制椭圆" << endl;
	}
};
//降低因为变化而要修改代码
//采用增加代码方式满足新需求
//统一接口
class Tool
{
public:
	void draw(Shape* parent)
	{
		parent->Draw();
	}
protected:
};
int main()
{
	testVirtual();
	printInfo(new Woman);
	Tool* pTool = new Tool;
	pTool->draw(new Circle);
	pTool->draw(new Rect);
	pTool->draw(new Triangle);
	pTool->draw(new Elliptical);
	return 0;
}
  • 纯虚函数也是虚函数只是纯虚函数是没有函数体的
virutal void print()=0;//在类中函数 这样写法
  • 抽象类:具有至少一个纯虚函数的类,叫做抽象类

    • 抽象类不能构建对象

    • 抽象类可以构建对象指针

  • 纯虚函数没有被重写,无论被继承多少次 都是纯虚函数,虚函数无论被继承多少次都是虚函数

#include <iostream>
using namespace std;
//抽象类
class Parent
{
public:
	virtual void print() = 0;		//纯虚函数
protected:
};
void testAbstract()
{
	//Parent object;  不能构建对象
	Parent* parent = nullptr;
}

//纯虚函数就是做ADT(abstract data type 抽象数据类型)过程
//stack  栈
class stack
{
public:
	//父类中所有的操作描述好
	virtual void push(int data) = 0;
	virtual void pop() = 0;
	virtual int top() const = 0;
	virtual bool empty() const = 0;
	virtual int size() const = 0;
};
//子类想要创建对象,必须重写父类的纯虚函数
//ADT: 具有强迫性,所有子类重写函数必须和父类的一模一样
class arrayStack :public stack
{
public:
	void push(int data)
	{

	}
	void pop()
	{

	}
	int top() const
	{
		return  1;
	}
	bool empty() const
	{
		return true;
	}
	int size() const
	{
		return 1;
	}
	//可以增加别的函数
	//可以增加别的成员
protected:
	int* array;
};
struct Node
{
	int data;
	Node* next;
};
class listStack :public stack
{
public:
	void push(int data)
	{

	}
	void pop()
	{

	}
	int top() const
	{
		return  1;
	}
	bool empty() const
	{
		return true;
	}
	int size() const
	{
		return 1;
	}
protected:
	Node* headNode;
};
void testStack(stack* pStack)
{
	pStack->push(1);
	while (!pStack->empty())
	{
		cout << pStack->top();
		pStack->pop();
	}
}

class A
{
public:
	virtual void print() = 0;
protected:
};
class B :public A
{
public:
	void print()
	{
		cout << "B" << endl;
	}
};
class C :public B
{
public:
	void print()
	{
		cout << "C" << endl;
	}
};
void Abtract()
{
	//B b;
	C c;  //一般抽象类只被继承一次就重写
	B* pc = new C;
	pc->print();
}
int main()
{
	testStack(new arrayStack);
	testStack(new listStack);
	Abtract();
	return 0;
}

虚析构函数

#include <iostream>
using namespace std;

class parent
{
public:
	//虚析构函数,不存在虚构造函数
	virtual ~parent()
	{
		cout << "父类析构" <<endl;
	}
	void print(){}

};
class son:public parent
{
public:
	~son()
	{
		cout << "子类析构" <<endl;
	}
	void print(){}
};

int main()
{
	//在用子类对象初始化父类指针,父类需要析构函数做内存释放
	parent* p = new son;
	p->print();
	delete p;
	return 0;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-09 18:05:39  更:2022-04-09 18:08:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:43:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码