我们为什么要在C++中使用虚函数
类中的成员函数分为静态成员函数和非静态成员函数,而非静态成员函数又分为普通函数和虚函数。
至于为什么虚函数必须是非静态成员函数,可以看一下:http://blog.csdn.net/leiming32/article/details/8619893
我们在类中定义函数的时候,在前面加上virtual就可以声明为虚函数。
接下来我们看一个例子:
#include<iostream>
#include<string>
using namespace std;
class Student
{
public:
Student(string n,string nam,int sco);
virtual void display();
protected:
string num;
string name;
int score;
};
Student::Student(string n,string nam,int sco)
{
num=n;
name=nam;
score=sco;
}
void Student::display()
{
cout<<"num:"<<num<<endl;
cout<<"name:"<<name<<endl;
cout<<"score:"<<score<<endl;
}
class Graduate:public Student
{
public:
Graduate(string n,string nam,int sco,string un);
virtual void display();
private:
string university;
};
Graduate::Graduate(string n,string nam,int sco,string un):Student(n,nam,sco),university(un){};
void Graduate::display()
{
cout<<"num:"<<num<<endl;
cout<<"name:"<<name<<endl;
cout<<"score:"<<score<<endl;
cout<<"university:"<<university<<endl;
}
int main()
{
Student *p;
p=new Student("001","QianShou",100);
p->display();
cout<<"==============没有节操的分割线================"<<endl;
p=new Graduate("001","QianShou",100,"SDNU");
p->display();
return 0;
}
运行结果:
/*
num:001
name:QianShou
score:100
==============没有节操的分割线================
num:001
name:QianShou
score:100
university:SDNU
*/
p是基类指针,当它指向基类的对象时,调用的display函数为基类中的成员函数,当它指向派生类的对象时,调用的display函数为派生类中的成员函数。
这就难免出现一个问题,我们为什么要用指向基类的指针指向派生类,然后再通过指针调用派生类中的成员函数呢?
为什么不直接建立一个指向派生类的指针,然后调用成员函数呢?这样都没有必要在基类中声明虚函数了。
我们考虑这样一个问题,如果我们要去一个城市的好多不同的地方,如果我们乘坐公交车的话,每去一个地方就需要选择不同的公交车;而如果我们乘坐出租车的话,我们只需要找一个出租车,然后不断告诉它不同的地点,它就能够带我们去不同的地方。
道理是相似的:
乘坐公交车:
假如一个基类有20个派生类,当我们分别访问这21个派生类和基类的时候,我们就需要为每一个类建立一个指针,然后通过不同的指针去访问不同的类的对象,就好像我们通过乘坐不同的公交车到达不同的地点一样。
乘坐出租车:
如果我们在基类中建立相应的虚函数,我们就只需要建立一个指向基类的指针。当我们需要访问该基类或者它的20个派生类的时候,我们只需将相应的类的地址赋给指向基类的指针,即可访问该派生类中的虚函数。就像我们在做出租车的时候,不断告诉司机我们的下一个地址一样。
我们为什么要在C++中使用虚函数的更多相关文章
- EC笔记,第二部分:9.不在构造、析构函数中调用虚函数
9.不在构造.析构函数中调用虚函数 1.在构造函数和析构函数中调用虚函数会产生什么结果呢? #; } 上述程序会产生什么样的输出呢? 你一定会以为会输出: cls2 make cls2 delete ...
- 关于在C#中构造函数中调用虚函数的问题
在C#中如果存在类的继承关系,应避免在构造函数中调用虚函数.这是由于C#的运行机制造成的,原因如下: 新建一个类实例时,C#会先初始化该类(对类变量赋值,并将函数记在函数表中),然后再初始化父类.构造 ...
- C++ 构造函数中调用虚函数
我们知道:C++中的多态使得可以根据对象的真实类型(动态类型)调用不同的虚函数.这种调用都是对象已经构建完成的情况.那如果在构造函数中调用虚函数,会怎么样呢? 有这么一段代码: class A { p ...
- C++中的虚函数解析[The explanation for virtual function of CPlusPlus]
1.什么是虚函数? ...
- C++箴言:避免构造或析构函数中调用虚函数
如果你已经从另外一种语言如C#或者Java转向了C++,你会觉得,避免在类的构造函数或者析构函数中调用虚函数这一原则有点违背直觉.但是在C++中,违反这个原则会给你带来难以预料的后果和无尽的烦恼. 正 ...
- 读书笔记 effective c++ Item 9 绝不要在构造函数或者析构函数中调用虚函数
关于构造函数的一个违反直觉的行为 我会以重复标题开始:你不应该在构造或者析构的过程中调用虚函数,因为这些调用的结果会和你想的不一样.如果你同时是一个java或者c#程序员,那么请着重注意这个条款,因为 ...
- C#中的虚函数及继承关系
转载:http://blog.csdn.net/suncherrydream/article/details/8423991 若一个实例方法声明前带有virtual关键字,那么这个方法就是虚方法. 虚 ...
- C++进阶--构造函数和析构函数中的虚函数
//############################################################################ /* 任何时候都不要在构造函数或析构函数中 ...
- 【校招面试 之 C/C++】第10题 C++不在构造函数和析构函数中调用虚函数
1.不要在构造函数中调用虚函数的原因 在概念上,构造函数的工作是为对象进行初始化.在构造函数完成之前,被构造的对象被认为“未完全生成”.当创建某个派生类的对象时,如果在它的基类的构造函数中调用虚函数, ...
- 【C++】C++中的虚函数与纯虚函数
C++中的虚函数 先来看一下实际的场景,就很容易明白为什么要引入虚函数的概念.假设我们有一个基类Base,Base中有一个方法eat:有一个派生类Derived从基类继承来,并且覆盖(Override ...
随机推荐
- Python - 批量改变文件名
import osimport sysimport datetime path = "E:\python_test"datename = '2016-02-11'a = datet ...
- CentOS 6.8安装Docker V1.0
rpm -Uvh http://dl.Fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm yum -y install do ...
- Git学习--版本回退
现在,你已经学会了修改文件,然后把修改提交到Git版本库,现在,再练习一次,修改readme.txt文件如下: Git is a distributed version control system. ...
- MySQL管理
http://www.yiibai.com/mysql/administration.html 在本节中,您将学习有关MySQL管理教程,包括MySQL服务器启动和关闭,MySQL服务器安全性,MyS ...
- centos type.h 编译错误问题
# ifndef __int8_t_defined # define __int8_t_defined __intN_t (, __QI__); __intN_t (, __HI__); __intN ...
- WPF之X名称空间学习
WPF的X名称空间都有什么呢?首先,盗用张图来说明: 我将就图表中的内容进行总结: 1.x:Array具有一个Iteams属性,它能暴漏一个ArratList实例,ArratList实例的内部成员类型 ...
- Maven:Resource Path Location Type Project configuration is not up-to-date with pom.xml. Run project configuration update
Maven构建项目的时候提示: Description Resource Path Location Type Project configuration is not up-to-date with ...
- QT:QString、QByteArray和char *的转换 【转载】
原文网址:http://blog.csdn.net/light1028/article/details/7899541 第一种,数据流的方式,这里只说从QByteArray转向QString. QBy ...
- oracle中merge的用法,以及各版本的区别 Create
Merge是一个非常有用的功能,类似于Mysql里的insert into on duplicate key. Oracle在9i引入了merge命令,通过这个merge你能够在一个SQL语句中对一个 ...
- HDU5468(dfs序+容斥原理)
Puzzled Elena Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)T ...