6、C++面向对象编程:虚函数、覆盖、多态与抽象类

1、虚函数

语法:

virtual 函数返回类型 函数名 (参数表)
{
    
    
	函数体
}

例子:定义虚函数
virtual void func()
{
    
    
	
}
//定义了一个虚函数,系统就会产生一个虚表。

结论:

  • 1、当类中含有一个虚函数时,系统就会自动分配一个虚表指针(*vptr),用来指向系统的虚表
  • 2、用户定义的所有虚函数都在虚表中
  • 3、虚表的地址永远都在对象空间的最前面
  • 4、子类会把父类的虚表也继承下来,子类父类共用一个虚表(实现多态的条件)

2、C++ 中的覆盖

隐藏: 子类 与 父类拥有一个同名函数,子类就会把父类的功能接口给隐藏掉。

假设要是用 父类接口
new_base a;
base &q=a; //通过对父类进行引用,再调用他的接口。
q.func(); //show_base

当基类拥有一个虚函数并在派生类中,对该虚函数进行了重写。 这种就是覆盖!!

覆盖的代码例子:

#include <iostream>
using namespace std;
class base
{
    
    
	public:
		int a;
		virtual void func() //声明了一个虚函数
		{
    
    
			cout << "show_base" << endl;
		}
};

class new_base :public base
{
    
    
	public:
		void func()//在派生类中,对该虚函数进行重写
		{
    
    
			cout << "show_new_base" << endl;
		}
};

int main()
{
    
    
	new_base a;
	a.show(); //show_new_base
	//通过基类把 派生隐藏的接口显示出来
	base &q=a;
	q.show(); //show_base
}

为什么可以覆盖??

在这里插入图片描述
覆盖的条件:

  • 1、基类必须要有虚函数
  • 2、派生类必须要重写基类的虚函数
  • 3、通过基类的指针或者引用,指向派生类,并调用重写的方法

只有满足上述三个条件才会出现这种情况

3、多态

一个对象,作用于不同的事物,所得到的结果是不一样的(一个函数可以实现多种不同的功能)。可以提高代码的复用性

静态多态: 在程序 《编译》的时候,已经确定将要执行的状态。
动态多态:在程序 《运行》的时候,才能确定执行的状态。 根据用户传递不同的对象,执行不同的状态。

动态多态的实现条件:

  • 1、基类要有虚函数
  • 2、派生类继承基类
  • 3、派生类重写基类的虚函数
  • 4、把派生类的对象赋值给基类的指针或者引用,通过基类调用被重写之后的接口

编写动态多态的案例:

//定义一个人
class person
{
    
    
	public:
	virtual void work() //设置为 虚拟的工作方式,不明确,所以是虚拟的
	{
    
    
		cout << "这个人我们不知道它能干嘛" <<endl;
	}
}

//把这些人的工作内容实例化
class JC:public person
{
    
    
	public:
	void work()
	{
    
    
		cout << "去抓小偷" << endl;
	}
};

class HS:public person
{
    
    
	public:
	void work()
	{
    
    
		cout << "去做核酸检测" << endl;
	}
};

class CS:public person
{
    
    
	public:
	void work()
	{
    
    
		cout << "上秋名山!!" << endl;
	}
};

//设计一个工作的接口
void do_work(person *q)//一个 do_work 的接口 , 作用不同的事物  ,得到的结果不一样(多态)
{
    
    
	//这个人去工作了
	q->work();
}

int main()
{
    
    
	//调用工作的函数
	do_work(new person);
	do_work(new JC);
	do_work(new HS);
	do_work(new CS);
}

4、虚析构

在这里插入图片描述
因为通过基类的指针去释放派生类的堆空间,系统是无法调用派生类的析构函数。所以就可能造成派生类构造函数中初始化的一些数据成员未被释放,造成资源的浪费!!!

虚析构的语法:

virtual ~析构函数{
    
    }
------------------
例子:
virtual ~new_base(){
    
    }

使用例子:

#include <iostream>
using namespace std;
class base
{
    
    
	public:
	base()
	{
    
    
		cout << "执行base的构造函数" << endl;
	}
	virtual ~base()
	{
    
    
		cout << "执行base的析构函数"<< endl;
	}
}

class new_base : public base
{
    
    
	public:
		new_base()
		{
    
    
			cout << "执行new_base的构造函数"<< endl;
			p = new char[1024];
			cout << "分配一块1024的堆空间" << (void*)p << endl;
		}
		
		virtual ~new_base()
		{
    
    
			cout << "执行new_base的析构函数" << endl;
			cout << "释放分配的堆空间" << (void *)p << endl;
			delete p;
		}
	private:
		char *p;
};

int main()
{
    
    
	//通过基类指针,指向派生类的对象
	base *p = new new_base;
	//通过基类的指针,释放派生类的对象空间
	delete p;
}

总结:

  • 析构函数不管是否用到多态技术, 最好都设置为虚析构。万无一失!!!

5、纯虚函数 与 抽象类

纯虚函数的定义:

virtual 函数返回类型 函数名(参数表) =0--------------------------------------
例子:
virtual void func()=0; //纯虚函数

抽象类:

  • 如果一个类中有纯虚函数,那么这个类就是抽象类

抽象类的特点:

  • 抽象类不能实例化
    在这里插入图片描述

提示:

  • 假设派生类没有对纯虚函数实例化,那么这个派生类还是抽象类

抽象类的作用:

  • 设计代码预留框架接口,让派生类去实现

抽象类的应用案例 :

假设我们想要开一家饮品店, 饮品店制作各种各样饮品 . 但是需要制作 什么饮料还不 知道,但是制作的过程大概知道。 把整个制作的过程给抽象出来。
1.加水 -> 2.加辅料 ->3.搅拌 -> 4.打包售卖 ,这些过程先抽象出来。进行实例化:
假设制作咖啡 : 1.加入热水 -> 2.加入咖啡豆 -> 3. 咖啡机进行搅拌 -> 4.装杯卖 18块钱 。
假设制珍珠奶茶 : 1.加入牛奶 -> 2.加入珍珠 -> 3. 手摇 -> 4.装杯卖 8块钱

#include <iostream>
using namespace std;

class make
{
    
    
public:
    // 加水
    virtual void water() = 0;
    // 加辅料
    virtual void fuliao() = 0;
    // 搅拌
    virtual void jiaoban() = 0;
    // 售卖
    virtual void shoumai() = 0;
};

class coffee : public make
{
    
    
public:
    // 重写基类虚函数
    void water()
    {
    
    
        cout << "加入热水" << endl;
    }
    void fuliao()
    {
    
    
        cout << "加入咖啡豆 " << endl;
    }
    void jiaoban()
    {
    
    
        cout << "咖啡机进行搅拌 " << endl;
    }
    void shoumai()
    {
    
    
        cout << "装杯卖 18块钱 " << endl;
    }
};

int main()
{
    
    
    make *p = new coffee;
    p->water();
    p->fuliao();
    p->jiaoban();
    p->shoumai();
}

猜你喜欢

转载自blog.csdn.net/qq_53402930/article/details/132410183