虚函数
来源:互联网 发布:盘古网络待遇 编辑:程序博客网 时间:2024/05/07 04:05
二、虚函数
在类的继承层次结构中,在不同的层次中可以出现同名同参(类型、个数)都相同的函数。在子类中调用父类的成员方法,可以使用子类对象调用时使用父类的作用域实现。
虚函数的作用是允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类中的同名函数。
举一个实例来说明使用虚函数与不使用虚函数的区别,基类和派生类中都有同名函数。
不使用虚函数:
Student.h
1. #ifndefPrograms_Student_h
2. #definePrograms_Student_h
3. usingnamespace std;
4.
5. class Student
6. {
7. public:
8. Student(int ,string,float);
9. voiddisplay();
10.protected:
11.int num;
12.stringname;
13.float score;
14.};
15.#endif
Student.ccp
1. #include<iostream>
2. #include<string>
3. #include"Student.h"
4. usingnamespace std;
5.
6. //定义构造函数
7. Student::Student(int n,stringnam,float s)
8. {
9. num=n;
10.name=nam;
11.score=s;
12.}
13.
14.voidStudent::display()
15.{
16.cout<<"num:"<<num<<"\nname:"<<name<<"\n score:"<<score<<"\n"<<endl;
17.}
Graduate.h
1. #ifndefPrograms_Graduate_h
2. #definePrograms_Graduate_h
3. #include"Student.h"
4. #include<string.h>
5. usingnamespace std;
6.
7. class Graduate:public Student
8. {
9. public:
10.Graduate(int ,string ,float,float);
11.voiddisplay();
12.private:
13.float pay;
14.};
15.#endif
Graduate.cpp
1. #include<iostream>
2. #include"Graduate.h"
3. #include"Student.h"
4. usingnamespace std;
5.
6. voidGraduate::display()
7. {
8. cout<<"num:"<<num<<"\nname:"<<name<<"\nscore:"<<score<<"\npay="<<pay<<endl;
9.
10.}
11.
12.Graduate::Graduate(int n,stringnam,float s,floatp):Student(n,nam,s),pay(p)
13.{
14.
15.}
main.cpp
1. #include<iostream>
2. #include"Student.h"
3. #include"Graduate.h"
4. usingnamespace std;
5.
6. int main(int argc,constchar * argv[])
7. {
8.
9. Students1(1000,"David",100);
10.Graduateg1(2000,"Jarry",50,20);
11.
12.Student*p=&s1;
13.p->display();
14.
15.p=&g1;
16.p->display();
17.return 0;
18.}
说明:定义一个Student类,让Graduate类继承Student类后,两个类中共同定义了一个display()方法,因为是在基类和派生类中分别定义的同名同参类,所以没有冲突,但是在调用的时候就出现了问题。我们在主函数中定义一个指针p指向父类对象的首地址,然后用指针p调用display()函数,没问题,我们可以打印出我们想要的数据。然后用指针p指向派生类Graduate的对象首地址,再次调用display()方法,你会发现Graduate中继承父类的成员对象没有被重写,还是父类中成员值,Graduate自己的成员没打印出来是有问题的,在此说明通过一个指针指向不同的类分别调用不同层次中的同名同参类是不行的。这就需要用到虚函数来解决此问题了。
我们在上述程序中作一点修改:在Student类中声明display()时,加一个关键字virtual即
virtual void display();
这样就把Student类display()声明成一个虚函数。这样就可以实现刚才想要的效果了。
说明:基类指针本来是用来指向基类对象的,如果用它指向派生类对象,则进行指针类型转换,将派生类对象的指针先转换为基类的指针,所以基类的指针指向的是派生类对象中的基类部分。
程序修改前,是无法通过基类指针去调用派生类对象中的成员函数的。虚函数突破这一限制,在派生类的基类部分中,派生类的虚函数取代了基类原来的虚函数,因此在使基类指针指向派生类对象后,调用虚函数时就调用了派生类的虚函数。只有用virtual声明了虚函数后才具有以上作用。如果不声明为虚函数,企图通过基类指针调用派生类的非虚函数是不行的。
把基类的某个成员函数声明为虚函数后,允许在其派生类中对该函数重新定义,赋予它新的功能,并且可以通过指向基类的指针指向同一类族中不同类的对象,从而调用其中的同名函数。由虚函数实现的动态多态性就是:同一类族中不同类的对象,对同一函数调用作出不同的响应。
虚函数的使用方法:
1、 在基类用virtual声明成员函数为虚函数。这样就可以在派生类中重新定义此函数,为它赋予新的功能,方便使用。
2、 在派生类中重新定义此函数,要求函数名、函数类型、函数参数个数和类型全部与基类的虚函数相同,并根据派生类的需要重新定义函数体。
3、 在主函数中定义一个基类指针指向基类对象,引用基类函数;指向派生类对象,引用派生类函数。
C++规定:一个成员函数被声明为虚函数时,派生类中的同名函数都自动成为虚函数。所以派生类中同名函数加不加virtual都是可以的,习惯上添加,程序易懂。
注意:如果在派生类中没有对基类的虚函数重新定义,则派生类简单地继承其直接基类的虚函数。
通过虚函数与指向基类对象的指针变量的配合使用,就能方便地调用同一类族中不同类的同名函数,只要先用基类指针指向即可。如果指针不断地指向同一类族中的不同类的对象,就能不断调用不同类的对象中的同名函数。
如果在基类中定义的非虚函数在派生类中被重新定义,如果用基类指针调用该成员函数,系统会调用对象中基类部分的成员函数;如果用派生类的指针调用该成员函数,则系统对调用派生类对象中的成员函数,这不是多态,是不同类型的指针,没有用到虚函数- 构造函数 虚函数
- 虚函数 inline函数
- 纯虚函数、虚函数、虚析构函数
- 虚函数,虚析构函数,虚函数表
- 普通函数,虚函数,纯虚函数
- 虚函数,纯虚函数,需析构函数
- 构造函数、析构函数、虚函数
- 构造函数 虚函数 虚析构函数
- 虚函数/构造函数/析构函数
- 构造函数&析构函数&虚函数
- 虚函数
- 虚函数
- 虚函数
- 虚函数
- 虚函数
- 虚函数
- 虚函数
- 虚函数
- 第一个Struts2项目
- 多态 重载与覆盖
- 编写合适的构造函数、拷贝构造函数、赋值操作符、析构函数(后三者一般同时出现,称为“大三元法则”),那么这个概念就完整并且不用再考虑其资源(内存)管理的问题。
- 函数htmlspecialchars
- VC中使用系统提供的线程池
- 虚函数
- 库克解释iPhone 4S的取名思路:S=Siri
- Android的GridView和Gallery结合Demo
- socket阻塞与非阻塞,同步与异步
- 飞机加油问题
- Nginx 反向代理https
- ArrayList用法
- HDU_2540 遮挡判断
- cpu超频