类虚函数

简介:   理解C++中继承层次的关键在于理解如何确定函数调用,确定函数调用遵循以下四个步骤: (1)首先确定进行函数调用的对象,引用或指针的静态类型。 (2)在该类中查找函数,如果找不到,就在直接基类中查找,如此循着类的继承链往上找,直到找到该函数或者查找完最后一个类。

 

  理解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中的定义的版本;

 

相关文章
|
5月前
|
C++
C++一分钟之-虚函数与抽象类
【6月更文挑战第21天】在C++中,虚函数与抽象类是多态的基础,增进类间耦合与灵活性。虚函数实现动态绑定,抽象类定义不可实例化的接口。关键点包括:记得使用`virtual`,避免滥用虚函数,确保派生类实现纯虚函数。抽象类不能直接实例化,派生类必须实现所有纯虚函数。通过实例代码学习和实践,能更好地掌握这些概念以优化代码设计。
47 2
|
C++
38.【C++ 虚函数 纯虚函数 虚基类 (最全详解)】(一)
38.【C++ 虚函数 纯虚函数 虚基类 (最全详解)】
53 0
|
C++
38.【C++ 虚函数 纯虚函数 虚基类 (最全详解)】(二)
38.【C++ 虚函数 纯虚函数 虚基类 (最全详解)】
111 0
|
3月前
|
编译器 C++
C++的基类和派生类构造函数
基类的成员函数可以被继承,可以通过派生类的对象访问,但这仅仅指的是普通的成员函数,类的构造函数不能被继承。构造函数不能被继承是有道理的,因为即使继承了,它的名字和派生类的名字也不一样,不能成为派生类的构造函数,当然更不能成为普通的成员函数。 在设计派生类时,对继承过来的成员变量的初始化工作也要由派生类的构造函数完成,但是大部分基类都有 private 属性的成员变量,它们在派生类中无法访问,更不能使用派生类的构造函数来初始化。 这种矛盾在C++继承中是普遍存在的,解决这个问题的思路是:在派生类的构造函数中调用基类的构造函数。 下面的例子展示了如何在派生类的构造函数中调用基类的构造函数:
37 1
|
6月前
|
Serverless C++
C++多态性、虚函数、纯虚函数和抽象类知识网络构造
C++多态性、虚函数、纯虚函数和抽象类知识网络构造
|
5月前
|
编译器
继承——虚函数
继承——虚函数
|
5月前
|
数据安全/隐私保护
继承——基类与派生类
继承——基类与派生类
|
存储 编译器 C++
<c++>虚函数与多态 | 虚函数与纯虚函数 | 多态的实现原理 | 虚析构函数
<c++>虚函数与多态 | 虚函数与纯虚函数 | 多态的实现原理 | 虚析构函数
136 0
|
C++
基类派生类多态虚函数?
通常在层次关系的根部有一个基类,其他类则直接或间接的从基类继承而来,这些继承得到的类称为派生类。基类负责定义在层次关系中所有类共同拥有的成员,而每个派生类定义各自特有的成员。
113 0
<c++> 类的继承 | 基类与派生类 | 构造函数与析构函数
<c++> 类的继承 | 基类与派生类 | 构造函数与析构函数
138 0