一,抽象类
1.纯虚函数的概念
纯虚函数是在父类中定义了一个只有声明而没有实现的函数,即使给出了纯虚函数的实现,那么编译器也会忽略。
2.纯虚函数的说明形式
virtual 返回值类型 函数名称(参数列表) = 0;
3.纯虚函数的意义
纯虚函数只存在了函数的声明,而不存在函数的实现,在继承中为子类提供了一个统一的接口,每一个子类对象都可以去实现它,在多态特性中便会根据需要的子类对象而调用相应的子类业务。
4.抽象类的概念
含有纯虚函数的类称为抽象类。
5.抽象类示例
# include<iostream> using namespace std; /* 动物类 */ class Animal { public: /* 纯虚函数 */ virtual void eat() = 0; /* 虚析构函数:保证子类的析构函数被调用正确 */ ~Animal() {}; }; /* 狗类 */ class Dog:public Animal { public: virtual void eat() { cout << "狗吃骨头..." << endl; } }; /* 猫类 */ class Cat :public Animal { public: virtual void eat() { cout << "猫吃鱼..." << endl; } }; /* 抽象类指针做函数返回值 */ Animal * get() { Animal * animal = new Cat; return animal; } /* 抽象类引用作函数参数 */ void set(Animal& animal) { animal.eat(); } int main() { /* 抽象类指针 */ Animal * animal1 = new Dog(); animal1->eat(); delete animal1; /* 抽象类引用 */ Cat cat; Animal& animal2 = cat; animal2.eat(); /* 抽象类指针做函数返回值 */ Animal * animal3 = get(); animal3->eat(); delete animal3; /* 抽象类引用作函数参数 */ Dog dog; set(dog); return 0; }
5.抽象类特点
- 抽象类不允许创建对象。
- 抽象类元素不能作为函数的返回值,不能作为函数的参数。
- 抽象类的指针和引用可以做函数参数,可以做返回值,可以指向子类对象。
- 抽象类的子类必须去实现纯虚函数,如果不实现,该类还是抽象类。
6.接口
在Java中存在接口的概念,并且Java中只允许单继承,但是允许接口的多实现。C++中的多继承存在二义性诟病,不建议使用,而且C++也没有提供接口的概念,但是我们可以使用抽象类来模拟接口,因此利用这一特性,我们可以使用抽象类模拟的继承实现接口的多实现,借用C++的多继承模拟出来的接口的多实现,即解决了C++多继承的二义性诟病,又极好的实现了大多数现在面向对象语言的接口的功能。
7.接口的案例
# include<iostream> using namespace std; class Interface { public: virtual void print() = 0; }; class Impl1 :public Interface { public: void print() { cout << "Impl1的实现" << endl; } }; class Impl2 :public Interface { public: void print() { cout << "Impl2的实现" << endl; } }; int main() { Interface * i1 = new Impl1; i1->print(); Interface * i2 = new Impl2; i2->print(); return 0; }
二,C语言实现多态
1.函数的三要素
函数的三要素为:函数名称,函数参数,函数返回值。
2.函数指针的概念
在C语言中我们可以定义指向函数的指针,被称为函数指针。函数的名称是函数的入口地址。
3.函数指针的定义
函数指针的定义格式:函数返回值类型 (* 函数指针名称)(函数参数列表);
4.函数的回调本质
函数的回调,就是利用了函数的指针实现的。首先我们提前约定一个格式,把函数的参数列表和函数的返回值类型规定好,又因为函数的名称是函数的入口地址,所以我们在函数指针使用的时候传入函数的名称(即函数的入口地址)就可以动态的调用符合约定格式的函数。
5.函数指针及函数的回调示例
# include<iostream> using namespace std; /* 定义加法函数 */ int add(int a, int b) { return a + b; } /* 定义减法函数 */ int sub(int a, int b) { return a - b; } /* 定义回调函数 */ int execFun(int(*fun)(int a, int b),int p_a,int p_b) { return fun(p_a, p_b); } int main() { /* 定义一个函数返回值为int,函数参数有两个int类型的函数指针 */ int(*fun)(int a, int b); /* 动态使得函数指针指向一个函数 */ fun = add; /* 调用函数指针进行运算 */ int r1 = fun(1, 2); cout << "r1 = " << r1 << endl; /* 回调函数:我们只需要传递要调用的函数和要计算的数值即可,回调函数帮我们自动调用并返回结果 */ fun = sub; int r2 = execFun(fun, 100, 200); return 0; }
6.函数回调的意义及多态
函数的回调最大的意义是在于不在同一个文件中,我们可以在一个文件中进行回调函数的约定,在另个文件中书写具体的函数,当在代码运行时,我们动态的改变函数指针使其指向不同的调用函数,也就实现了C语言的多态。