在多态中,通常父类中虚函数的实现是毫无意义的,主要是调用子类重写的内容。
因此,我们可以将虚函数修改为纯虚函数。
纯虚函数语法:virtual 返回值类型 函数名(参数列表) = 0;
当类中有了纯虚函数,这个类就称之为抽象类。
#include <iostream>
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 <iostream>
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.通过域操作符指定使用哪一条路上的方法。
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
{
};