1多态的分类
1)静态多态:函数重载和运算符重载属于静态多态,复用函数名
2)动态多态:派生类和虚函数实现运行时多态(重点)
一、静态多态和动态多态的区别?
1)、静态多态的函数地址早绑定-编译时确定函数地址
2)、动态多态的函数地址晚绑定-运行时确定函数地址
代码示例:
class Animal
{
public:
virtual void speak()
{
cout << "动物在说话" << endl;
}
};
//猫类
class Cat:public Animal
{
public:
void speak()
{
cout << "小猫在说话" << endl;
}
};
//执行说话的函数
//地址早绑定,在编译阶段确定函数地址 (输出为:动物在说话)
//如果想执行让猫说话,那么这个函数地址就不能提前绑定,需要在运行阶段进行绑定,地址晚绑定
//加入virtual 就是地址晚绑定,运行时确定函数地址(小猫在说话)
void dospeak(Animal &Animal) //Animal &animal =cat;
{
Animal.speak();
}
void test01()
{
Cat cat;
dospeak(cat);
}
int main()
{
test01();
cout << sizeof(Animal);
}
用一张图来解释代码块:
补充知识:
空类的大小为:1。
只有虚函数的大小为:4,因为有一个虚函数指针。
动态多态的满足条件:
1).有继承关系
2).子类重写父类函数
动态多态的使用:
父类的指针或者引用,指向子类对象 父类的指针或者引用,指向子类对象
二、纯虚函数和抽象类
在多态中,通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写的内容,因此可以将虚函数改为纯虚函数。
纯虚函数语法: virtual 返回值类型 函数名(参数列表)=0
当类中有了纯虚函数,这个类也称为抽象类。
抽象类的特点:
1)无法实例化对象
2)子类必须重写抽象类中的纯虚函数,否则也属于抽象类
三、虚析构和纯虚析构`
多态使用时。如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码`
解决方法:将父类中的析构函数改为虚析构或者纯虚析构
虚析构和纯虚析构共性:
1)可以解决父类指针释放子类对象
2)都需要有具体的函数实现
虚析构和纯虚析构区别:
如果是纯虚析构,该类属于抽象类,无法实例化对象
代码表示:
class Animal
{
public:
Animal()
{
cout << "Animal的构造函数调用" << endl;
}
/* virtual~Animal()
{
cout << "Animal的析构函数调用" << endl;
}
*/
//纯虚析构需要声明也要实现
//有了纯虚析构之后,这个类也属于抽象类
~Animal()
{
cout << "Animal的析构函数调用" << endl;
}
virtual void speak() = 0;
};
/*Animal::~Animal()
{
cout << "Animal的析构函数调用" << endl;
}
*/
class Cat :public Animal
{
public:
void speak()
{
cout << *M_name << "小猫在说话" << endl;
}
//开辟在堆上的内存
string *M_name;
Cat(string name)
{
cout << "Cat构造函数调用" << endl;
M_name = new string(name);
}
//堆区的属性在析构函数中释放掉
~Cat()
{
if (M_name != NULL)
{
cout << "cat的析构函数调用" << endl;
delete M_name;
M_name = NULL;
}
}
};
void test01()
{
Animal *animal = new Cat("Tom");
animal->speak();
//父类指针在析构时候,不会调用子类中析构函数,导致子类如果有堆区属性,造成数据泄露
delete animal;
}
int main()
{
test01();
}
结果为:
从结果可以看出我们在子类中开辟的堆区的属性,应该是要在子类的析构函数中将其释放。可以结果显示父类的指针释放并没有调用子类的析构函数。
当我们将父类的析构函数改为虚析构函数或者纯虚析构函数时:
virtual~Animal()
{
cout << "Animal的析构函数调用" << endl;
}
或者
我们的结果为:子类的析构函数被调用,则子类对象在堆区开辟的空间被释放。
总结:
1.虚析构函数和纯虚析构函数都用来解决父类指针释放子类对象
2.如果子类没有堆区数据,可以不用写为虚析构函数或纯虚析构
3.拥有纯虚析构的类也属于抽象类