本篇是自己阅读加上自己对“多态”的理解,若有不足之处,感谢指出~
多态 多态最常见的用法就是声明基类类型的指针,利用该指针指向任意一个子类对象,调用相应的虚函数,可以根据指向的子类的不同而实现不同的方法 。如果没有使用虚函数的话,即没有利用C++多态性,则利用基类指针调用相应的函数的时候,将总被限制在基类函数本身,而无法调用到子类中被重写过的函数。因为没有多态性,函数调用的地址将是固定的,因此将始终调用到同一个函数,这就无法实现“一个接口,多种方法”的目的了。
在C++ Primer有关于OOP编程的描述是这样的。
OOP不仅仅是将数据和方法合并为类定义;还有助于创建可重用的代码,这将减少大量的工作(继承、类的复用)。
封装 (信息隐藏)可以保护数据,使其免遭不适当的访问(使得代码模块化);
多态 让您能够为运算符和函数创建多个定义,通过编程上下文来确定使用哪个定义;
编译时多态:通过重载函数实现
运行时多态性:通过虚函数实现
继承 让您能够使用旧类派生出新类(扩展已存在的代码)。
这些都是面向对象(OOP)所指的特性。还包括:
在C++面试中很有可能会问你C++的三个特性:封装、继承、多态 。
有关于这三点特性,从设计模式中会受益许多,一个好的建议就是去学习设计模式。推荐《Easy搞定设计模式》这本PDF,网上可以搜到。
关于多态,C++ primer 给的定义包括多个方面:
函数重载
函数多态是C++在C语言的基础上新增的功能,默认参数让您能够使用不同数目的参数调用同一个函数,而函数多态(函数重载)让您能够使用多个同名的函数。术语“多态”指的是拥有多种形式,因此函数多态允许函数可以有多种形式。类似地,术语“函数重载”指的是可以有多个同名的含糊,因此对名称进行了重载。
类继承:有些继承关系是多态的,这意味着相同的方法名称可能导致依赖于对象类型的行为。(如下代码所示)
运算符重载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 class Fruit {public : virtual void getName () { cout << "一种水果" << endl;; } void getColor () { cout << "水果的颜色" << endl; } };class Apple : public Fruit {public : virtual void getName () { cout << "我是苹果" << endl; } virtual void getColor () { cout << "红色苹果" << endl;; } };int main () { Fruit fruit; Apple apple; Fruit *anotherFruit = &fruit; anotherFruit->getName (); anotherFruit->getColor (); anotherFruit = &apple; anotherFruit->getName (); anotherFruit->getColor (); system ("pause" ); return 0 ; }
输出如下:
再谈“接口” 不同对象调用使用相同方法实现不同操作,也即,方法完成的行为取决于调用该方法的对象。说着有点拗口,我自己理解就是类层面的“重载”。怎么去理解?代码!还是刚才的两个类,额外添加一个Pear类。
1 2 3 4 5 6 7 8 9 10 11 12 class Fruit {public : virtual void getName () = 0 ; virtual void getColor () = 0 ; };
但凡是纯虚函数,子类继承必须全部重定义!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Apple : public Fruit {public : virtual void getName () { cout << "我是苹果" << endl; } virtual void getColor () { cout << "红色苹果" << endl;; } };class Pear : public Fruit {public : virtual void getName () { cout << "我是犁" << endl; } virtual void getColor () { cout << "黄犁" << endl;; } };
创建指针对象指向不同的子类,实现不同的操作。
1 2 3 4 5 6 7 8 9 10 int main () { Fruit *apple = new Apple; Fruit *pear = new Pear; apple->getName (); apple->getColor (); pear->getName (); pear->getColor (); return 0 ; }
输出如下: