多态:对同一消息有不同响应;
分为静态多态和动态多态:
静态多态:编译期多态,看指针类型;
基类A 派生类B A,B里有同名的函数fun
B b();
A* = &b;
A->fun();
调用的是A的fun,不会调用b的fun
动态多态:运行时多态,看内存;
A里的 fun 前面加了 virtual, 前面的就会调用B的fun
虚函数:
声明:在函数声明前加上virtual关键字
定义:函数定义中不需要加上virtual关键字;
继承:虚函数会被继承,仍然为虚函数,并且子类可以重写(覆盖)(在后面写override)父类的虚函数;
(virtual关键字可以省略,override可以省略)
虚函数:子类重写了父类的虚函数(与父类虚函数的地址不相同)
虚指针:指向虚表;
虚表:多个格子(每一个格子存放虚函数的地址)
哪些函数不能定义为虚函数?
1.普通非成员函数
2.构造函数(无参/带参/拷贝):在构造函数前,还没有产生虚指针
3.内联函数:内联编译期展开,virtual是动态多态;
4.静态成员函数:可以直接通过类名调用
5.友元函数:不属于类;
纯虚函数::
只有声明没有定义(函数体)
纯虚函数就是虚函数的函数主体=0,也就是没有主体
virtual void fun() = 0;
想要在基类中定义虚函数,以便在派生类中重新定义该函数更好地适用于对象,但是您在基类中又不能对虚函数给出有意义的实现,这个时候就会用到纯虚函数
注意:
①虚函数和纯虚函数在多态中,存在差异,虚函数在派生类中可以选择是否重写该虚函数,如果派生类重写了虚函数,则调用子类的函数,否则调用基类的函数。而纯虚函数必须在派生类中实现该纯虚函数。
②当类中存在纯虚函数,则该类为 抽象类
抽象类:具有一个及以上纯虚函数的类称为抽象类;
特点:
1.抽象类中可以有不是纯虚函数的方法;
2.抽象类不能创建对象,可以创建抽象类的指针或者引用;
3.子类只有实现了抽象类的所有纯虚方法后,才不是抽象类;
成员函数指针:指向类的成员函数;
1.定义:
返回值类型(类名::*函数指针名)(形参表);
2.赋值/初始化:
&类名::成员函数名
3.怎么通过成员函数指针调用成员函数?
1.(对象.*函数指针)(实参表);
2.(对象指针->*函数指针)(实参表);
//定义一个成员函数指针,指向Drug的use方法
void(Drug::*pFunc)() = &Drug::use;
Drug drug(".."," ");
(drug.*pFunc)();//.*
Drug* pDrug = new Drug("","");
(pDrug->*pFunc)();//->*
类的内存:
1.空类:1个字节
2.内存对齐原则
3.具有1个及以上虚函数的类:+4个字节
什么情况下要将父类的析构函数写成虚函数?
父类指针指向子类对象时,释放子类对象的内存时,需要将父类的析构函数写成虚函数;
哪些运算符不能重载?
. :: .* ->* sizeof ?:
----------------------------------
一、函数的重载(本类重载)
函数重载具有以下特性:
1、相同的范围(在同一个类内部);
2、函数名相同,形参列表不同,函数返回类型不能作为重载的依据;
3、virtual关键字可有可无;
4、重载是在编译期间根据参数类型和个数决定函数调用;
二、函数的隐藏(隐藏基类)
隐藏是指派生类的函数屏蔽了与其同名的基类函数。
1、如果派生类的函数与基类的函数同名,但是参数不同。此时无论有无virtual关键字,基类的函数将被隐藏(注意别和重载混淆)。
2、如果派生类和基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别和覆盖混淆)。
三、函数的覆盖(多态)
派生类函数覆盖基类函数,只作用于派生类函数。一般具有如下特性:
1、不同范围(分别位于派生类和基类);
2、基类与派生类中函数的声明完全相同(函数名、形参列表、返回类型);
3、基类函数必须有virtual关键字(虚函数);
4、覆盖情况下,编译器会在运行时根据对象的实际类型来确定要调用的函数。
----------------------------------
Bag.h
#pragma once
class Array;
class Prop;
class Bag
{
public:
Bag();
//1.拾取物品
void getPr