虚函数的相关知识点

概念

联编:

链接1)(链接2

1. 联编是指一个计算机程序自身彼此关联的过程,在这个联编过程中,需要确定程序中的操作调用(函数调用)与执行该操作(函数)的代码段之间的映射关系;按照联编所进行的阶段不同,可分为 态联编和动态联编;

2. 通常来说联编就是将模块或者函数合并在一起生成可执行代码的处理过程,同时对每个模块或者函数调用分配内存地址,并且对外部访问也分配正确的内存地址,它是计算机程序彼此关联的过程。按照联编所进行的阶段不同,可分为两种不同的联编方法:静态联编和动态联编。

静态联编和动态联编的定义:

静态联编是指在编译阶段就将函数实现和函数调用关联起来,因此静态联编也叫早绑定,在编译阶段就必须了解所有的函数或模块执行所需要检测的信息,它对函数的选择是基于指向对象的指针(或者引用)的类型,C语言中,所有的联编都是静态联编,并且任何一种编译器都支持静态联编。

动态联编是指在程序执行的时候才将函数实现和函数调用关联,因此也叫运行时绑定或者晚绑定,动态联编对函数的选择不是基于指针或者引用,而是基于对象类型,不同的对象类型将做出不同的编译结果。C++中一般情况下联编也是静态联编,但是一旦涉及到多态和虚拟函数就必须要使用动态联编了。下面将介绍一下多态。

多态的实现:

字面的含义是具有多种形式或形态。C++多态有两种形式,动态多态和静态多态;动态多态是指一般的多态,是通过类继承和虚函数机制实现的多态;静态多态是通过模板来实现,因为这种多态实在编译时而非运行时,所以称为静态多态。

实现过程:

静态联编:主要是通过函数重载和操作数重载来实现

动态联编:主要是靠虚函数来实现

 代码理解和分析:(链接

 1 #include <iostream> 
 2 using namespace std;
 3  
 4 class Shape {
 5    protected:
 6       int width, height;
 7    public:
 8       Shape( int a=0, int b=0)
 9       {
10          width = a;
11          height = b;
12       }
13       int area()
14       {
15          cout << "Parent class area :" <<endl;
16          return 0;
17       }
18 };
19 class Rectangle: public Shape{
20    public:
21       Rectangle( int a=0, int b=0):Shape(a, b) { }
22       int area ()
23       { 
24          cout << "Rectangle class area :" <<endl;
25          return (width * height); 
26       }
27 };
28 class Triangle: public Shape{
29    public:
30       Triangle( int a=0, int b=0):Shape(a, b) { }
31       int area ()
32       { 
33          cout << "Triangle class area :" <<endl;
34          return (width * height / 2); 
35       }
36 };
37 // 程序的主函数
38 int main( )
39 {
40    Shape *shape;
41    Rectangle rec(10,7);
42    Triangle  tri(10,5);
43  
44    // 存储矩形的地址
45    shape = &rec;
46    // 调用矩形的求面积函数 area
47    shape->area();
48  
49    // 存储三角形的地址
50    shape = &tri;
51    // 调用三角形的求面积函数 area
52    shape->area();
53    
54    return 0;
55 }
View Code
输出:
Parent class area Parent class area

代码中没有使用virtual关键字,这是静态联编的过程,因为 area() 函数在程序编译期间就已经设置好了,参考下面的解释更好理解。

基类的指针指向派生类的对象当调用同名的成员函数时:(原文链接

1)如果在基类中成员函数为虚函数,那么基类指针调用的就是派生类的同名函数。virtual void display();

     可以这么理解:因为该函数是虚的,所以会找真正实现的那个函数,所以调用派生类B中的 B class virtual display.

2)如果基类中成员函数为非虚函数,则调用的是基类的成员函数。void show();

     因为基类是非虚的,已经完全实现了,所以没有必要再调用派生类的了,就调用基类的A class show()

如果改为下面代码:

 1 class Shape {
 2    protected:
 3       int width, height;
 4    public:
 5       Shape( int a=0, int b=0)
 6       {
 7          width = a;
 8          height = b;
 9       }
10       virtual int area()
11       {
12          cout << "Parent class area :" <<endl;
13          return 0;
14       }
15 };
View Code
输出:
Rectangle class area Triangle class area

总结:

  • 基类指针加virtual关键字,所有的派生类都会默认自动加上virtual关键字。

  含义:

  • 若类中成员函数被说明为虚函数,改成原函数在派生类中可能有不同的实现
  • 使用该成员函数操作指针或者引用所标识的对象时,对该成员函数调用可以采用动态联编方式

猜你喜欢

转载自www.cnblogs.com/fanhua666/p/11532367.html