多态性是面向对象程序设计的又一个重要思想,关于多态的详尽描述,请看本人的收藏https://www.cnblogs.com/hust-ghtao/p/3512461.html。这篇博文中,详尽的探讨了多态的一些特性。
在此,我仅仅以白话的方式描述为何要引入多态:
子类继承了基类的方法,但子类可以改变这些这些方法以适应自己的特性,而不是只能照搬基类的方法。现在面临这样一个问题:访问的便捷性和权限。
我们可以使用对象名的方式来访问方法,或者使用类指针,类引用的方式来访问,这都是完全OK的。关键问题在于,假如我们有很多派生子类,比如1000个,当我们要访问具有类似功能(但又有所差异的)的接口时,难道还要用很多对象名去访问吗?显然不科学,一方面,我们这样做,使得程序缺乏灵活性,易读性,还费时费力。
那么有没有一种方法使得我们能够用一种统一的方式来进行这种访问呢?有的,那就是虚函数。
见一段代码:
1 # include "iostream" 2 using namespace std; 3 class Base 4 { 5 public: 6 void funpublic() 7 { 8 cout << "基类的成员函数" << endl; 9 } 10 }; 11 12 class child1 :public Base 13 { 14 public: 15 void funpublic() 16 { 17 cout << "派生类child1的成员函数" << endl; 18 } 19 }; 20 21 22 class child2 :public Base 23 24 { 25 public: 26 void funpublic() 27 { 28 cout << "派生类child2的成员函数" << endl; 29 } 30 }; 31 int main() { 32 Base * p1, *p2, *p3, base;//假如在基类中不使用虚函数,则当我们定义一个基类指针时,就注定我们所访问的方法就是基类方法,但如果我们想访问派生类方法,就 33 //没有这个访问权限;但若我们定义派生类指针,则只能够指向某一个派生类,无法指向其他派生类(包括基类)。但程序初衷是:设计一种方式 34 //这种方式能够访问基类和派生类中方法相同(实现方式有所差异)的接口,能够随着我们所调用的对象的所属类,自动调用相应的方法(如果有) 35 //这时,就要采用相应的虚函数的方法。 36 child1 obj1; 37 child2 obj2; 38 base = obj1; 39 base.funpublic(); 40 Base &aliasbase = obj2; 41 aliasbase.funpublic(); 42 p1 = &obj1; 43 p2 = &obj2; 44 p1->funpublic(); 45 p2->funpublic(); 46 p2 = new child1; 47 p2->funpublic(); 48 p3 = new child2; 49 p3->funpublic(); 50 system("pause"); 51 return 0; 52 }
上述这段代码中没有使用虚函数,我们看一下结果:
我们本意是试图通过指针去访问子类的方法,但是失败了,原因是:倘若我们偷懒,想只定义一个基类指针,就能完成对所有子类同一方法的访问,但是很明显,基类指针不具备这样的访问权限,也就是,当我们定义一个基类指针时,就注定了我们基类指针所指向的对象的指针(这里应该叫地址)会被转化为基类的地址,也就是,我们没有办法去访问真正意义上的派生类指针,当然,我们定义一个派生类指针,也不能够访问其他派生类的方法,当然,更不能访问基类方法。
那么有没有一种方法,能够帮助我们一劳永逸,只定义一个指针就能访问其他所有派生类同名方法呢?有的
1 # include "iostream" 2 using namespace std; 3 class Base 4 { 5 public: 6 virtual void funpublic() 7 { 8 cout << "基类的成员函数" << endl; 9 } 10 }; 11 12 class child1 :public Base 13 { 14 public: 15 void funpublic() 16 { 17 cout << "派生类child1的成员函数" << endl; 18 } 19 }; 20 21 22 class child2 :public Base 23 24 { 25 public: 26 void funpublic() 27 { 28 cout << "派生类child2的成员函数" << endl; 29 } 30 }; 31 int main() { 32 Base * p1, *p2, *p3, base;//假如在基类中不使用虚函数,则当我们定义一个基类指针时,就注定我们所访问的方法就是基类方法,但如果我们想访问派生类方法,就 33 //没有这个访问权限;但若我们定义派生类指针,则只能够指向某一个派生类,无法指向其他派生类(包括基类)。但程序初衷是:设计一种方式 34 //这种方式能够访问基类和派生类中方法相同(实现方式有所差异)的接口,能够随着我们所调用的对象的所属类,自动调用相应的方法(如果有) 35 //这时,就要采用相应的虚函数的方法。 36 child1 obj1; 37 child2 obj2; 38 base = obj1; 39 base.funpublic(); 40 Base &aliasbase = obj2; 41 aliasbase.funpublic(); 42 p1 = &obj1; 43 p2 = &obj2; 44 p1->funpublic(); 45 p2->funpublic(); 46 p2 = new child1; 47 p2->funpublic(); 48 p3 = new child2; 49 p3->funpublic(); 50 system("pause"); 51 return 0; 52 }
这段代码与前面一段代码仅仅多了一个关键字,但是结果大不相同:
可见,当我们将类方法声明为虚方法的时候,大大提高了基类指针的访问权限,使得基类指针能够真正意义上访问子类方法,因此,使用虚函数的方法实现多态是一种优秀的程序设计理念。
关于虚函数和多态细节信息请见我开篇转载博客。
原文地址:https://www.cnblogs.com/shaonianpi/p/10294347.html