在上一篇 C++ 学习笔记 (六) 继承- 子类与父类有同名函数,变量 中说了当父类子类有同名函数时在外部调用时如果不加父类名则会默认调用子类的函数。C++有函数重写的功能需要添加virtual关键字,当时写上篇博文的时候在想那么既然默认使用子类的同名函数那么这个virtual有什么意义呢?
这篇博文主要讲述 多态:一句相同的语句能有不同的实现。
当父类和子类有同名函数,调用时牵扯到了指针那么就跟virtual有关系了。
看以下几种情况:
定义两个类:父类子类有同名函数print();
1 class Parent 2 { 3 public: 4 5 void print() //子类的和父类的函数名字一样 6 { 7 cout<<"Parent 打印 "<<endl; 8 } 9 10 }; 11 12 class Child : public Parent 13 { 14 public: 15 16 void print() 17 { 18 cout<<"Child 打印 "<<endl; 19 } 20 21 };
1.当父类和子类都有同名函数prin()t时,使用Parent 类指针,指向子类对象或者父类对象调用的函数都是父类的函数。
Parent *base = NULL;
5 base = &p1; //父类对象 6 base->print(); //执行父类的打印函数 7 8 base = &c1; //子类对象 9 base->print(); //也是执行父类函数
2.使用引用,当引用是父类时调用的函数也是父类的同名函数
Parent &base2 = p1; base2.print();//调用父类函数 Parent &base3 = c1; //base3是c1 的别名 base3.print(); //调用父类函数
3.函数传参为父类 类型时,无论传入子类还是父类都只执行父类的函数
void howToPrint(Parent *base) //传参为父类的指针
{ base->print(); }
void howToPrint2(Parent &base) //传参为父类的引用 { base.print(); } //函数调用 均执行父类的函数 howToPrint(&p1); howToPrint(&c1); howToPrint2(p1)
howToPrint2(c1);
总结:
其实上面三个情景下当我们一个指针指向了子类,或者引用子类那么我们希望调用函数的时候是调用子类的函数,但是实际情况却不是这样。这时候就需要virtual关键字了。
1 lass Parent 2 { 3 public: 4 5 virtual void print() //子类的和父类的函数名字一样 6 { 7 cout<<"Paren打印 "<<endl; 8 } 9 10 }; 11 12 class Child : public Parent 13 { 14 public: 15 16 virtual void print() //virtual 父类写了virtual,子类可写 可不写 17 { 18 cout<<"Child 打印 "<<endl; 19 } 20 21 };
使用了virtual关键字定义的函数,那么在上述三种情况下只要指针是指向子类,或是引用子类那么往后的调用就按照我们的预想调用子类里的函数。再回顾一下这句话:
多态:一句相同的语句能有不同的实现。
举例:
void howToPrint(Parent *base) //传参为父类的指针
{ base->print(); } 传入的指针决定了最后执行的函数,出入父类指针则执行父类的print函数,出入父类的派生类则调用这个派生类的print函数,这样一句相同的语句就有了不同的实现。
void howToPrint(Parent *base) //传参为父类的指针