动态绑定,多态(带你从本质了解多态)(下)

简介: 动态绑定,多态(带你从本质了解多态)
3.多继承无函数覆盖下的虚函数表

看完了单继承,我们来看看多继承的虚函数表:

#include "stdafx.h"
class Base1{
public:
  int a;
  int b;
  virtual void Base1_1(){
    printf("Base1:Function_1...\n");
  }
  virtual void Base1_2(){
    printf("Base1:Function_2...\n");
  }
};
class Base2{
public:
  int c;
  int d;
  virtual void Base2_1(){
    printf("Base2:Function_1...\n");
  }
  virtual void Base2_2(){
    printf("Base2:Function_2...\n");
  }
};
class Sub1:public Base1,Base2{
public:
  int e;
  virtual void Sub_1(){
    printf("Sub1:Sub_1...\n");
  }
  virtual void Sub_2(){
    printf("Sub1:Sub_2...\n");
  }
};
int main(int argc, char* argv[])
{
  typedef void (*Function)(void);
  Sub1 b;
  int* p;
  p = (int*)&b;
  int* function;
  function = (int*)(*p);
  Function pFn;
  for(int i=0;i<6;i++){
    pFn = (Function)*(function+i);
    pFn();
  }
  return 0;
}

根据我们上面的讲解,应该在虚函数表中有6个函数地址,但是程序在运行的时候照样提醒我:该地址不允许访问,说明在虚函数表中,不足6个函数。

我们看看程序输出窗口:

那么到底哪里出了问题?父类Base2中的虚函数去哪了?

我们先来看一下Sub的大小:

#include "stdafx.h"
class Base1{
public:
  int a;
  int b;
  virtual void Base1_1(){
    printf("Base1:Function_1...\n");
  }
  virtual void Base1_2(){
    printf("Base1:Function_2...\n");
  }
};
class Base2{
public:
  int c;
  int d;
  virtual void Base2_1(){
    printf("Base2:Function_1...\n");
  }
  virtual void Base2_2(){
    printf("Base2:Function_2...\n");
  }
};
class Sub1:public Base1,Base2{
public:
  int e;
  virtual void Sub_1(){
    printf("Sub1:Sub_1...\n");
  }
  virtual void Sub_2(){
    printf("Sub1:Sub_2...\n");
  }
};
int main(int argc, char* argv[])
{
  printf("%d",sizeof(Sub1));
  return 0;
}

我们可以看到程序输出窗口输出了28,我们来看看Sub的成员:继承了Base1的a和b,继承了Base2的c和d,自己的成员e,还有一张虚表,应该一共是24,可是它为什么输出了28?

其实通过课堂上老师的讲解我们已经知道:多重继承函数时会有多张虚表,而Base2的虚表就存在于this指针的第二个成员,他是Base2的虚表。

二.前期绑定和后期绑定

我们知道当程序调用函数的时候,有两种调用方式,一种是直接调用函数的地址,这种地址在程序编译的时候就已经写死了,另一种是通过一个地址,间接调用函数。

这里介绍一个名词:绑定,将函数与地址链接在一起的过程,叫做绑定。

直接调用函数的方式,在编译时就已将函数与地址绑定,我们称为(前期)编译期绑定

间接调用函数的方式,在运行的时候才进行绑定,我们称这种方式为(运行期)动态绑定或者晚绑定

注意:

只有virtual函数是动态绑定

三.多态

了解了前面的过程,多态的概念这里一句话就明白了:动态绑定还有另一个名字:多态。

这里给出多态的书面定义:

C++中的多态分为静态多态和动态多态。静态多态是函数重载,在编译阶段就饿能够确定调用哪个函数。动态多态是由继承产生的,指同一个属性或行为在基类和各派生类中具有不同的语义,不同的对象根据所接受的消息做出不同的响应,这种现象称为多态。

多态的实现需要满足三个条件:

(1)基类中声明虚函数

(2)派生类重写基类的虚函数

(3)将基类指针指向派生类对象,通过基类指针访问虚函数

我们来看看多态的具体实现,看看多态到底是什么:

#include "stdafx.h"
class Base{
public:
  int x;
  Base(){
    x=100;
  }
  virtual void Base_1(){
    printf("Base:Function_1...\n");
  }
  virtual void Base_2(){
    printf("Base:Function_2...\n");
  }
};
class Sub:public Base{
public:
  int e;
  Sub(){
    x=200;
  }
  virtual void Base_1(){
    printf("Sub1:Sub_1...\n");
  }
};
void Test(Base* p){
  int n = p->x;
  printf("%d\n",n);
  p->Base_1();
  p->Base_2();
}
int main(int argc, char* argv[])
{
  Base b;
  Base* p = &b;
  Test(p);
  return 0;
}

首先我们定义了一个基类对象,并且通过基类指针去访问函数,我们来看看程序输出框:

我们定义了基类对象,并且通过基类指针去访问函数,当然是没有任何问题的。

接下来我们看看多态的实现:

创建一个基类,再创建一个派生类,将基类函数覆盖,通过基类指针访问派生类:

#include "stdafx.h"
class Base{
public:
  int x;
  Base(){
    x=100;
  }
  virtual void Base_1(){
    printf("Base:Function_1...\n");
  }
  virtual void Base_2(){
    printf("Base:Function_2...\n");
  }
};
class Sub:public Base{
public:
  int e;
  Sub(){
    x=200;
  }
  virtual void Base_1(){
    printf("Sub1:Sub_1...\n");
  }
};
void Test(Base* p){
  int n = p->x;
  printf("%d\n",n);
  p->Base_1();
  p->Base_2();
}
int main(int argc, char* argv[])
{
  Sub b;
  Base* p = &b;
  Test(p);
  return 0;
}

我们来看看程序输出窗口:

我们可以看到,基类中属性的值也被改变,并且基类中函数也被覆盖,这就是我们所说的多态,同一个属性或行为在基类和各派生类中具有不同的语义,不同的对象根据所接受的消息做出不同的响应。

相关文章
|
7月前
|
存储 C++ 容器
第十四章:C++虚函数、继承和多态详解
第十四章:C++虚函数、继承和多态详解
61 0
|
2月前
多态和动态绑定的区别是什么?
【10月更文挑战第14天】多态和动态绑定是面向对象编程中两个重要的概念,但它们有着不同的含义和作用。
28 2
|
6月前
|
C++
C++一分钟之-继承与多态概念
【6月更文挑战第21天】**C++的继承与多态概述:** - 继承允许类从基类复用代码,增强代码结构和重用性。 - 多态通过虚函数实现,使不同类对象能以同一类型处理。 - 关键点包括访问权限、构造/析构、菱形问题、虚函数与动态绑定。 - 示例代码展示如何创建派生类和调用虚函数。 - 注意构造函数初始化、空指针检查和避免切片问题。 - 应用这些概念能提升程序设计和维护效率。
44 2
|
7月前
|
存储 安全 编译器
【C/C++ 多态核心 20240115更新】C++虚函数表:让多态成为可能的关键
【C/C++ 多态核心 20240115更新】C++虚函数表:让多态成为可能的关键
55 0
|
存储 编译器 C++
【C++】多态及原理
【C++】多态及原理
51 0
再次理解多态概念
再次理解多态概念
66 0
动态绑定,多态(带你从本质了解多态)
动态绑定,多态(带你从本质了解多态)
【C++】多态中虚函数的底层理解
【C++】多态中虚函数的底层理解
【C++】多态中虚函数的底层理解
|
编译器 C++
【C++】多态(万字详解) —— 条件 | 虚函数重写 | 抽象类 | 多态的原理(上)
【C++】多态(万字详解) —— 条件 | 虚函数重写 | 抽象类 | 多态的原理(上)
171 0
【C++】多态(万字详解) —— 条件 | 虚函数重写 | 抽象类 | 多态的原理(上)