三、多态
一个函数接口可以实现不同的状态(一个接口函数多个功能)
1、多态分类
(1)静态多态:地址早绑定,编译阶段确定函数地址。代表:函数重载、运算符重载
(2)动态多态:地址晚绑定,运行阶段确定函数地址.
2、多态的实现
(1)实现条件:
1)类之间需要有继承关系
2)实现多态的函数需要以virtual来进行声明. (虚函数)
3)父类中的虚函数需要被子类重写
重写:返回值、函数名、参数都必须一致.
(2)语法
class A
{
virtual void fun(int_ _n1);
};
class B:pub1ic A
{
virtual void fun(int_ n1); //重写A中的虚函数。
};
(3)多态的优点:实际开发中,建议多用多态设计程序
1) 结构清晰,便于理解
2) 利于后期代码扩展、维护.实现了对修改屏蔽、对扩展开放.
(4)多态接口实现:
需要使用父类指针或父类引用指向子类对象,直接将子类对象赋值给父类对象是不行的.
1)
Base *b =
new Son1; //父类指针指向子类对象
b->fun(); //调用 子类中的函数。
2)Son1 s1;
Base &b = s1;
b. funO; / /调用子类中的函数
Base b2;
b2 = s1;
代码01):多态的实现
#include <iostream>
using namespace std;
class Animal
{
public:
virtual void Speak()
{
cout<<"animal speak"<<endl;
}
};
class Cat:public Animal
{
public:
virtual void Speak()
{
cout<<"cat speak"<<endl;
}
};
class Dog:public Animal
{
public:
virtual void Speak()
{
cout<<"dog speak"<<endl;
}
};
void AnimalSpeak(Animal &a1)
{
a1.Speak();
}
void test01()
{
Animal a2;
AnimalSpeak(a2);
Dog d1;
AnimalSpeak(d1);
Cat c1;
AnimalSpeak(c1);
}
int main(int argc, char *argv[])
{
test01();
return 0;
}
代码02):多态的优点
#include <iostream>
using namespace std;
#include <iostream>
using namespace std;
class Calculator
{
public:
Calculator():_num1(0), _num2(0)
{
}
virtual int CalculateFun()
{
return 0;
}
int _num1;
int _num2;
};
class AddCal: public Calculator //利于后期代码扩展、维护.
{
public:
AddCal()
{
_num1 = 0;
_num2 = 0;
}
AddCal(int n1, int n2)
{
_num1 = n1;
_num2 = n2;
}
int CalculateFun()
{
return _num1 + _num2;
}
};
int CalResultFun(Calculator &cal)
{
int ret = cal.CalculateFun();
return ret;
}
void test01()
{
AddCal c1(23, 56);
cout << CalResultFun(c1) << endl;
}
int main()
{
test01();
return 0;
}
3、虚函数
(1)就是virtual 修饰的成员函数.
(2)虚函数要求必须有实现过程,不能只是声明.
class A
{
virtual void fun(int); //声 明
}
void A: :fun(int_ n1) //实现过程
{
}
(3)纯虚函数:
1)有时候,父类里面的虚函数根本没有实现的必要,此时可以声明为纯虚函数.不用具体实现。
class A
virtual void fun(int) = 0; //纯虚函数声明
2) 有纯虚函数的类被称为抽象类,抽象类不能实例化对象.
4、析构函数
在多态的使用过程中,如果子类对象空间开辟到堆区(使用new方式),那么父类指针在释放时无法调用子类的析构代码。将父类中的析构改为虚析构,则可以解决该问题.