纯虚函数和抽象类

在多态中,通常父类中虚函数的实现是毫无意义的,主要是调用子类重写的内容。
因此,我们可以将虚函数修改为纯虚函数。
纯虚函数语法:virtual 返回值类型 函数名(参数列表) = 0;
当类中有了纯虚函数,这个类就称之为抽象类。

#include 
using namespace std;

//纯虚函数与抽象类
class Base{
public:
	//父类虚函数实现是豪无意义的,可以修改为纯虚函数。
	//纯虚函数语法:virtual 返回值类型 函数名(参数列表) = 0;
	virtual void func() = 0;    //纯虚函数

	//只要类中有一个纯虚函数,这个类称之为抽象类。
	//抽象类的特点:
	//1. 无法实例化对象
	//2. 抽象类的子类必须重写父类的纯虚函数,否则也属于抽象类。
};

class Son:public Base{
public:
	//由于子类现在没有重写父类的纯虚函数,所以子类Son属于抽象类。
	/*
	virtual void func()
	{
		cout << "Son func()的调用" << endl;
	}
	*/
};

int main(int argc,char *argv[])
{
	//Base *b = new Son;  //父类指针指向子类对象
	//b->func();
	
	//Base b;
	//new Base;
	

	Son s;

	return 0;
}
/********************************
PS C:\Users\32781\Desktop\love_you\02> g++ .\demo1.cpp
.\demo1.cpp: 在函数‘int main(int, char**)’中:
.\demo1.cpp:37:6: 错误:不能将变量‘s’声明为具有抽象类型‘Son’
   37 |  Son s;
      |      ^
.\demo1.cpp:17:7: 附注:因为下列虚函数在‘Son’中为纯虚函数:
   17 | class Son:public Base{
      |       ^~~
.\demo1.cpp:9:15: 附注:        ‘virtual void Base::func()’
    9 |  virtual void func() = 0;    //纯虚函数
      |               ^~~~
PS C:\Users\32781\Desktop\love_you\02>  
********************************/

案例描述:
制作饮品的大致流程为:煮水  --  冲泡   ---  倒入杯中   ---   加入辅料
利用多态的技术实现本案例,提供抽象制作饮品类,提供子类制作咖啡与茶。

例如:
冲咖啡
1、煮农夫山泉。    2、冲泡咖啡。
3、倒入玻璃杯中。4、加糖与牛奶。

冲茶
1、煮矿泉水。       2、冲泡茶叶。
3、倒入小茶杯中。4、加入柠檬。

#include 
using namespace std;

//饮品抽象类
class AbstractDrinking{
public:
	//煮水
	virtual void Boil() = 0;

	//冲泡
	virtual void Brew() = 0;

	//倒入杯中
	virtual void PourInCup() = 0;

	//加入辅料
	virtual void PutSomething() = 0;

	//制作饮品流程
	void makeDrink()
	{
		Boil();
		Brew();
		PourInCup();
		PutSomething();
	}
};

class Coffee:public AbstractDrinking{
public:
	//子类重写父类的纯虚函数
	virtual void Boil()
	{
		cout << "煮农夫山泉" << endl;
	}

	virtual void Brew()
	{
		cout << "冲泡咖啡豆" << endl;
	}

	virtual void PourInCup()
	{
		cout << "倒入玻璃杯中" << endl;
	} 

	virtual void PutSomething()
	{
		cout << "加入糖和牛奶" << endl;
	}
};

class Tea:public AbstractDrinking{
public:
	//子类重写父类的纯虚函数
	virtual void Boil()
	{
		cout << "煮矿泉水" << endl;
	}

	virtual void Brew()
	{
		cout << "冲泡茶叶" << endl;
	}

	virtual void PourInCup()
	{
		cout << "倒入小茶杯中" << endl;
	} 

	virtual void PutSomething()
	{
		cout << "加入柠檬" << endl;
	}
};



void doWork(AbstractDrinking *abs)  //父类的指针指向子类的对象
{
	abs->makeDrink();
	delete abs;
}

int main(int argc,char *argv[])
{
	doWork(new Coffee);

	cout << "------------------" << endl;

	doWork(new Tea);

	return 0;
}

菱形继承

纯虚函数和抽象类_第1张图片 

解决菱形继承中的二义性问题

1.通过域操作符指定使用哪一条路上的方法。 
      temp.base_a::show();  
      temp.base_b::show(); 

2.在派派生类中重写出现二义性的接口
 class base_c : public base_a,public base_b
{
	public :
	base_c(){cout << "base_c" << endl;}
	~base_c(){cout << "~base_c" << endl;}
   void show()
   {
       cout <<  "show base_c"  << endl;
   }
};

.最优的解决方法,利用《虚继承》,把base放入虚表中

/****************
语法:
class 类名: virtual 继承方式 父类名
{
};
虚继承--(在创建对象的时候会创建一个虚表)
A:virtual public D 
B:virtual public D
****************/
class base
{
};
//虚继承 base ->base 就会放入虚表中
class base_a : virtual  public base
{
};
//虚继承 base ->base 就会放入虚表中 
class base_b :virtual  public base
{
};
//!! 所有亲缘关系的类共用一个虚表 
class base_c : public base_a,public base_b
{
};

纯虚函数和抽象类_第2张图片

 

你可能感兴趣的:(c++)