类虚函数

  理解C++中继承层次的关键在于理解如何确定函数调用,确定函数调用遵循以下四个步骤:

(1)首先确定进行函数调用的对象,引用或指针的静态类型。

(2)在该类中查找函数,如果找不到,就在直接基类中查找,如此循着类的继承链往上找,直到找到该函数或者查找完最后一个类。如果不能在类或其相关基类中找到该名字,则调用是错误的。

(3)一旦找到了该名字,就进行常规类型检查,查看如果给定找到的定义,该函数调用是否合法。

(4)假定函数调用合法,编译器就生成代码。如果函数是虚函数且通过引用或指针调用,则编译器生成代码以确定根据对象的动态类型运行哪个函数版本,否则,编译器生成代码直接调用函数。

 1 class Base{
 2 public:
 3     virtual int fcn();
 4 }
 5
 6
 7 class D1: public Base{
 8 public:
 9     //hides fcn in the base; this fcn is not virtual
10     int fcn(int);   //nonvirtual function hides D1::fcn(int)
11     //D1 inherits definition of Base::fcn()
12 }
13
14 class D2 : public D1{
15 public:
16     int fcn(int);   //nonvirtual function hides D1::fcn(int)
17     int fcn();      //redefines virtual fcn from Base
18 }
19
20 D1中的fcn版本没有重定义Base的虚函数fcn,相反,它屏蔽了基类的fcn。
21 结果D1有两个名为fcn的函数:1、类从Base继承了一个名为fcn的虚函数,
22 2、类又定义了自己的名为fcn的非虚成员函数,该函数接受了一个int的
23 形参。但是,从Base继承的虚函数不能通过D1对象(或D1的引用或指针)
24 调用,因为该函数被fcn(int)的定义屏蔽了。
25
26 类D2重定义了它继承了两个函数,它重定义了Base中定义的fcn的原始版本
27 并重定义了D1中定义的非虚版本;
28 //通过基类调用被屏蔽的虚函数
29 //通过基类类型的引用或指针调用函数时,编译器将在基类中查找该函数而忽略派生类:
30     Base bobj;  D1 d1obj; D2 d2obj;
31     Base *bp1 = &bobj, *bp2 = &d1obj, *bp3 = &d2obj;
32     bp1->fcn();     //ok:virtual call, call Base::fcn at run time
33     bp2->fcn();     //ok:virtual call, call Base::fcn at run time
34     bp3->fcn();     //ok:virtual call, call D2::fcn at run time
35
36 三个指针都是基类类型的指针,因此通过在Base中查找fcn来确定这三个调用,
37 所以这些调用是合法的;另外,因为fcn是虚函数,所以编译器会生成代码,
38 在运行时基于引用或指针所绑定的对象的实际类型进行调用。在bp2的情况,
39 基本对象是D1类的,D1类没有重定义不接受实参的虚函数版本,通过bp2的函数
40 调用(在运行时)调用Base中的定义的版本;
时间: 2024-10-21 03:31:33

类虚函数的相关文章

MFC浅析(7) CWnd类虚函数的调用时机、缺省实现

CWnd类虚函数的调用时机.缺省实现 FMD(http://www.fmdstudio.net) 1. Create 2. PreCreateWindow 3. PreSubclassWindow 4. PreTranslateMessage 5. WindowProc 6. OnCommand 7. OnNotify 8. OnChildNotify 9. DefWindowProc 10. DestroyWindow 11. PostNcDestroy CWnd作为MFC中最基本的与窗口打交

C++虚函数的陷阱--派生类对象的基类函数调用基类虚函数出错

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">最近写程序的时候发现,派生类对象的基类函数如果调用基类虚函数,则它将调用的是派生类的对应函数,而不是我想调用的基类的对应函数.</span> 下面用一个例子来说明: //基类 class Base { public: void funA(); virtual void fun

模板类 &amp; 虚函数

1 class faux 2 { 3 public: 4 template <typename T> 5 virtual void do() // member function templates cannot be virtual 6 {} 7 }; 8 9 10 template <typename T> 11 class vrai 12 { 13 public: 14 virtual void do(T v) // ok! 15 {} 16 }; 为什么 faux 中不行呢

基类中定义的虚函数在派生类中重新定义时,其函数原型,包括返回类型、函数名、参数个数、参数类型及参数的先后顺序,都必须与基类中的原型完全相同 but------&gt; 可以返回派生类对象的引用或指针

您查询的关键词是:c++primer习题15.25 以下是该网页在北京时间 2016年07月15日 02:57:08 的快照: 如果打开速度慢,可以尝试快速版:如果想更新或删除快照,可以投诉快照. 百度和网页 http://bbs.csdn.net/topics/380238133 的作者无关,不对其内容负责.百度快照谨为网络故障时之索引,不代表被搜索网站的即时页面. 首页 精选版块 移动开发 iOS Android Qt WP 云计算 IaaS Pass/SaaS 分布式计算/Hadoop J

C++ Primer 学习笔记33_面向对象编程(4)--虚函数与多态(一):多态、派生类重定义、虚函数的访问、 . 和-&gt;的区别、虚析构函数、object slicing与虚函数

C++ Primer学习笔记33_面向对象编程(4)--虚函数与多态(一):多态.派生类重定义.虚函数的访问. . 和->的区别.虚析构函数.object slicing与虚函数 一.多态 多态可以简单地概括为"一个接口,多种方法",前面讲过的重载就是一种简单的多态,一个函数名(调用接口)对应着几个不同的函数原型(方法). 更通俗的说,多态行是指同一个操作作用于不同的对象就会产生不同的响应.或者说,多态性是指发出同样的消息被不同类型的对象接收时有可能导致完全不同的行为. 多态行分

【整理】C++虚函数及其继承、虚继承类大小

参考文章: http://blog.chinaunix.net/uid-25132162-id-1564955.html http://blog.csdn.net/haoel/article/details/1948051/ 一.虚函数与继承 1.空类,空类单继承,空类多继承的sizeof #include <iostream> using namespace std; class Base1 { }; class Base2 { }; class Derived1:public Base1

C++中虚函数工作原理和(虚)继承类的内存占用大小计算

一.虚继承情况下类的内存大小计算 当每个基类中有多个虚函数时,并且在虚继承的情况下,内存是如何分配的,如何计算类的大小,下面举例说明: #include<iostream> using namespace std; class A { public: int a; virtual void aa(){}; }; class D { public: virtual void dd(){}; }; class C { public: virtual void cc(){}; }; class B

关于C++类中访问权限的若干疑问(虚函数访问权限)

下面这样一个程序:(以下程序都是在VS2010下实现) 1: class Base 2: { 3: public: 4: virtual void func() 5: { 6: cout<<"Base virtual func"<<endl; 7: } 8: }; 9: 10: class Derived: public Base 11: { 12: private: 13: virtual void func() 14: { 15: cout<<&

OOP2(虚函数/抽象基类/访问控制与继承)

通常情况下,如果我们不适用某个函数,则无需为该函数提供定义.但我们必须为每个虚函数都提供定义而不管它是否被用到了,这因为连编译器也无法确定到底会适用哪个虚函数 对虚函数的调用可能在运行时才被解析: 当某个虚函数通过指针或引用调用时,编译器产生的代码直到运行时才能确定应该调用哪个版本的函数.被调用的函数是与之绑定到指针或引用上的对象的动态类型相匹配的那一个 注意:动态绑定只有当我们通过指针或引用调用虚函数时才会发生.当我们通过一个具有普通类型(非引用非指针)的表达式调用虚函数时,在编译时就会将调用