转载:什么是虚函数

    虚函数联系到多态,多态联系到继承。所以本文中都是在继承层次上做文章。没了继承,什么都没得谈。

下面是对C++的虚函数这玩意儿的理解。

一,  什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你就应该从这里开始)

简单地说,那些被virtual关键字修饰的成员函数,就是虚函数。虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异而采用不同的策略。下面来看一段简单的代码

class A{

public:

void print(){ cout<<”This is A”<<endl;}

};

class B:public A{

public:

void print(){ cout<<”This is B”<<endl;}

};

int main(){   //为了在以后便于区分,我这段main()代码叫做main1

A a;

B b;

a.print();

b.print();

}

通过class A和class B的print()这个接口,可以看出这两个class因个体的差异而采用了不同的策略,输出的结果也是我们预料中的,分别是This is A和This is B。但这是否真正做到了多态性呢?No,多态还有个关键之处就是一切用指向基类的指针或引用来操作对象。那现在就把main()处的代码改一改。

int main(){   //main2

A a;

B b;

A* p1=&a;

A* p2=&b;

p1->print();

p2->print();

}

运行一下看看结果,哟呵,蓦然回首,结果却是两个This is A。问题来了,p2明明指向的是class B的对象但却是调用的class A的print()函数,这不是我们所期望的结果,那么解决这个问题就需要用到虚函数

class A{

public:

virtual void print(){ cout<<”This is A”<<endl;}  //现在成了虚函数了

};

class B:public A{

public:

void print(){ cout<<”This is B”<<endl;}  //这里需要在前面加上关键字virtual吗?

};

毫无疑问,class A的成员函数print()已经成了虚函数,那么class B的print()成了虚函数了吗?回答是Yes,我们只需在把基类的成员函数设为virtual,其派生类的相应的函数也会自动变为虚函数。所以,class B的print()也成了虚函数。那么对于在派生类的相应函数前是否需要用virtual关键字修饰,那就是你自己的问题了。

现在重新运行main2的代码,这样输出的结果就是This is A和This is B了。

现在来消化一下,我作个简单的总结,指向基类的指针在操作它的多态类对象时,会根据不同的类对象,调用其相应的函数,这个函数就是虚函数。
																来自百度  onlinewan
时间: 2024-11-19 13:43:38

转载:什么是虚函数的相关文章

【转载】 C++多继承中重写不同基类中相同原型的虚函数

本篇随笔为转载,原文地址:C++多继承中重写不同基类中相同原型的虚函数. 在C++多继承体系当中,在派生类中可以重写不同基类中的虚函数.下面就是一个例子: class CBaseA { public: virtual void TestA(); }; class CBaseB { public: virtual void TestB(); }; class CDerived : public CBaseA, public CBaseB { public: virtual void TestA()

C++虚函数解析(转载)

虚函数详解第一篇:对象内存模型浅析 C++中的虚函数的内部实现机制到底是怎样的呢? 鉴于涉及到的内容有点多,我将分三篇文章来介绍. 第一篇:对象内存模型浅析,这里我将对对象的内存模型进行简单的实验和总结. 第二篇:继承对象的构造和析构浅析,这里我将对存在继承关系的对象的构造和析构进行简单的实验和总结. 第三篇:虚函数的内部机制浅析,这里我将对虚函数内部的实现机制进行实验总结. 我使用的编译器是VS2008,有不足或者不准确的地方,欢迎大家拍砖(我个人非常迫切的希望得到大家的指正),我会及时修正相

C++构造函数和析构函数能否声明为虚函数?(转载)

构造函数为什么不能是虚函数 从存储空间角度,虚函数对应一个指向vtable虚函数表的指针,这大家都知道,可是这个指向vtable的指针其实是存储在对象的内存空间的.问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还没有实例化,也就是内存空间还没有,怎么找vtable呢?所以构造函数不能是虚函数. 从使用角度,虚函数主要用于在信息不全的情况下,能使重载的函数得到对应的调用.构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀.所以构造函数没有必要是虚函数.虚函数的作用

[转载]C++虚函数浅析

原文:http://glgjing.github.io/blog/2015/01/03/c-plus-plus-xu-han-shu-qian-xi/ 感谢:单刀土豆 C++虚函数浅析 JAN 3RD, 2015 1:59 AM | COMMENTS 一 引言 C++面向对象语言的一大特性就是抽象,在程序设计上的体现就是鼓励面向接口编程,而不要面向具体实现编程.这里所说的抽象和接口与C++的多态性密切相关.C++的多态分为静态多态(编译时多态)和动态多态(运行时多态)两大类.静态多态通过重载.模

构造函数为什么不能是虚函数 ( 转载自C/C++程序员之家)

从存储空间角度,虚函数对应一个指向vtable虚函数表的指针,这大家都知道,可是这个指向vtable的指针其实是存储在对象的内存空间的.问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还没有实例化,也就是内存空间还没有,怎么找vtable呢?所以构造函数不能是虚函数. 从使用角度,虚函数主要用于在信息不全的情况下,能使重载的函数得到对应的调用.构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀.所以构造函数没有必要是虚函数.虚函数的作用在于通过父类的指针或者引用来

【转载】C/C++杂记:虚函数的实现的基本原理

原文:C/C++杂记:虚函数的实现的基本原理 1. 概述 简单地说,每一个含有虚函数(无论是其本身的,还是继承而来的)的类都至少有一个与之对应的虚函数表,其中存放着该类所有的虚函数对应的函数指针.例: 其中: B的虚函数表中存放着B::foo和B::bar两个函数指针. D的虚函数表中存放的既有继承自B的虚函数B::foo,又有重写(override)了基类虚函数B::bar的D::bar,还有新增的虚函数D::quz. 提示:为了描述方便,本文在探讨对象内存布局时,将忽略内存对齐对布局的影响.

[转载]虚函数在构造函数中,已经失去了虚函数的动态绑定特性

class A { public: A() { Print(); } virtual void Print() { printf("A is constructed.\n"); } }; class B: public A { public: B() { Print(); } virtual void Print() { printf("B is constructed.\n"); } }; int _tmain(int argc, _TCHAR* argv[])

转载:C++多态性 &amp; C++纯虚函数

C++编程语言是一款应用广泛,支持多种程序设计的计算机编程语言.我们今天就会为大家详细介绍其中C++多态性的一些基本知识,以方便大家在学习过程中对此能够有一个充分的掌握. 多态性可以简单地概括为“一个接口,多种方法”,程序在运行时才决定调用的函数,它是面向对象编程领域的核心概念.多态(polymorphism),字面意思多种形状. C++多态性是通过虚函数来实现的,虚函数允许子类重新定义成员函数,而子类重新定义父类的做法称为覆盖(override),或者称为重写.(这里 我觉得要补充,重写的话可

虚函数(转载)

一般继承(无虚函数覆盖) 下面,再让我们来看看继承时的虚函数表是什么样的.假设有如下所示的一个继承关系: 请注意,在这个继承关系中,子类没有重载任何父类的函数.那么,在派生类的实例中,其虚函数表如下所示: 对于实例:Derive d; 的虚函数表如下: 我们可以看到下面几点: 1)虚函数按照其声明顺序放于表中. 2)父类的虚函数在子类的虚函数前面. 我相信聪明的你一定可以参考前面的那个程序,来编写一段程序来验证. 一般继承(有虚函数覆盖) 覆盖父类的虚函数是很显然的事情,不然,虚函数就变得毫无意