c++面向对象高级编程 学习十六 vptr和vtbl

当一个类中有一个或多个虚函数时,内存中会多一个虚指针(vptr,virtual pointer),指向一个虚表(vtbl,virtual table)

父类有虚函数,则子类一定有虚函数

在下图示意图中,我们可知,B继承A,C继承B。
A有两个虚函数,B继承A则也有两个虚函数,同时B对虚函数vfunc1进行了重写,同理,C继承B,则C也有两个虚函数,C对虚函数vfunc1也进行了重写。故在内存中,A B C对应的虚函数vfunc2是同一个均为A::vfunc2,对应的虚函数vfunc1分别为A::vfunc1,B::vfunc1,C::vfunc1。

在这里插入图片描述
c++编译器遇到函数调用时,会有两个考量,是静态绑定还是动态绑定,静态绑定是call xxx地址,即一定调用到某个地址,动态绑定可以调用到不同的地址

动态绑定需符合三个条件:

  • 通过指针调用(对象调用函数是静态绑定
  • 指针是向上的关系,向上关系是指,比如 父类 名称 = new 子类(),这样的关系即是一种向上的关系
  • 调用的是虚函数

虚函数的这种用法,称之为多态

示例程序:

#include<iostream>
using namespace std;class A {
public:A(int data1, int data2) :m_data1(data1), m_data2(data2) {}virtual void vfunc1() { cout << "调用的是A的vfunc1"<< endl; }virtual void vfunc2() { cout << "调用的是A的vfunc2" << endl; }void func1() { cout << "调用的是A的func1" << endl; }void func2() { cout << "调用的是A的func2" << endl; }void getData() {cout << "A的m_data1:" << m_data1 << ",A的m_data2:" << m_data2 << endl;}
private:int m_data1, m_data2;
};class B:public A {
public:B(int n1,int n2,int n3) :A(n1,n2), m_data3(n3){}virtual void vfunc1() { cout << "调用的是B的vfunc1" << endl; }void func2() { cout << "调用的是B的func2" << endl; }void getData() {A::getData();cout << "B的m_data3:" << m_data3  << endl;}
private:int m_data3;
};class C :public B {
public:C(int n1, int n2, int n3,int n4,int n5):B(n1,n2,n3) , m_data1(n4), m_data4(n5) {}virtual void vfunc1() { cout << "调用的是C的vfunc1" << endl; }void func2() { cout << "调用的是C的func2" << endl; }void getData() {B::getData();cout << "C的m_data1:" << m_data1 << ",C的m_data4:" << m_data4 << endl;}
private:int m_data1, m_data4;
};

测试程序:

int main()
{A a(1,2);a.vfunc1();a.vfunc2();a.func1();a.func2();a.getData();cout << endl;B b(3,4,5);b.vfunc1();b.vfunc2();b.func1();b.func2();b.getData();cout << endl;C c(6,7,8,9,10);c.vfunc1();c.vfunc2();c.func1();c.func2();c.getData();cout << endl;A* d = new B(1,3,5);d->vfunc1();d->vfunc2();d->func1();d->func2();d->getData();cout << endl;A* d2 = new C(1, 3, 5,7,9);d2->vfunc1();d2->vfunc2();d2->func1();d2->func2();d2->getData();system("pause");return 0;
}

输出结果:

调用的是A的vfunc1
调用的是A的vfunc2
调用的是A的func1
调用的是A的func2
A的m_data1:1,A的m_data2:2调用的是B的vfunc1
调用的是A的vfunc2
调用的是A的func1
调用的是B的func2
A的m_data1:3,A的m_data2:4
B的m_data3:5调用的是C的vfunc1
调用的是A的vfunc2
调用的是A的func1
调用的是C的func2
A的m_data1:6,A的m_data2:7
B的m_data3:8
C的m_data1:9,C的m_data4:10调用的是B的vfunc1
调用的是A的vfunc2
调用的是A的func1
调用的是A的func2
A的m_data1:1,A的m_data2:3调用的是C的vfunc1
调用的是A的vfunc2
调用的是A的func1
调用的是A的func2
A的m_data1:1,A的m_data2:3

从输出结果中,我们可以看出,当对函数进行重写后,子类在调用函数时会调用重写后的函数。当函数是虚函数时,若我们按照父类 名称 = new 子类() 的形式生成指针,则该指针在调用函数时,若调用的函数是虚函数,则其会调用子类重写后的虚函数,若调用的函数不是虚函数,则无论子类对该函数是否重写,调用的均为父类的函数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/446586.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

英语口语Week16 Thursday

英语文章 It is an impossibility that everything runs smoothly in everyday life. Where there is trouble, there could be anxiety.Anxiety is a common phenomenon; you are not the only one carrying it. But, it could be somewhat poisonous if you don’t let it o…

c++面向对象高级编程 学习十七 const, new, delete

文章目录常量成员函数new和delete常量成员函数 常量成员函数是不改变成员数据。 当成员函数的const和non-const版本同时存在时&#xff0c;const object只能调用const版本&#xff0c;non-const object只能调用non-const版本。因此&#xff0c;可以看出&#xff0c;const是函…

codeforces 467A-C语言解题报告

题目网址 题目解析 1.输入n个房间,再每一行输入现有的p个人,和一共可以容纳的q人数,如果q-p>2则计数1 代码 #include<stdio.h> #include<stdlib.h> #include<string.h>int main() {int n0,p0,q0;int count0,i;scanf("%d",&n);for(i0;i&…

使用引用的方式交换数据的数值

#include <iostream>void swap(int &a,int &b){a ^ b;b ^ a;a ^ b; } int main(){int num1 10;int num2 20;swap(num1,num2);std::cout << num1 << std::endl;std::cout << num2 << std::endl; }

C++STL与泛型编程 侯捷 (1)

泛型编程&#xff08;Generic Programming&#xff0c;GP&#xff09;&#xff0c;就是使用template&#xff08;模板&#xff09;为主要工具来编写程序。 重要网页&#xff1a; http://www.cplusplus.com/ https://en.cppreference.com/w/ http://gcc.gnu.org/

codeforces 136A-C语言解题报告

题目网址 题目解析 1.输入每个人给第几个人发礼物(1–n), 输出每个人收到第几个人发的礼物 2.因为1–n,所以for循环也使用1–n output[input[j]]j; 代码 #include<stdio.h> #include<stdlib.h> #include<string.h> int main() {int n0;scanf("%d&…

static内容相关介绍学习

说一下static关键字的作用 当程序执行到函数内部定义的变量时&#xff0c;编译器为它在栈上分配空间&#xff0c;函数在栈上分配的空间在此函数执行结束时会释放掉&#xff0c;这样就产生了一个问题: 如果想将函数中此变量的值保存至下一次调用时&#xff0c;如何实现&#xf…

C++STL与泛型编程(2) 第一个C++ STL Application

文章目录STL六大部件STL六大部件代码示例时间复杂度前闭后开区间auto关键字的用法STL六大部件 容器 分配器 算法 迭代器 适配器 仿函数 容器要放东西&#xff0c;东西要占用内存&#xff0c;分配器可支持容器解决内存问题。算法处理容器中的数据。迭代器是容器和算法之间的桥…

codeforces 344A-C语言解题报告

题目网址 题目解析 1.有10和01两种,同性相斥,异性相吸 2.01是1,使用pre去记录前一个,写出所有情况 0110 1001 分为一组 代码 #include<stdio.h> #include<stdlib.h> #include<string.h> int main() {int n0;int i0;int c0;int pre-1;int count0;scanf(&…

JAVA 程序执行进行计时,用于验证程序执行的时间

package com.example.algorithm.demo.class1;public class Hello {public static void main(String[] args) {long start System.nanoTime();//程序开始时间System.out.println(start);System.out.println("Hello");long end System.nanoTime();System.out.println…

C++STL与泛型编程__侯捷视频_学习博客_总目录

CSTL与泛型编程 侯捷 &#xff08;1&#xff09;: c重要网站相关 CSTL与泛型编程&#xff08;2&#xff09; 第一个C STL Application&#xff1a; STL六大部件代码示例&#xff0c;容器前闭后开区间&#xff0c;auto关键字的用法示例 CSTL与泛型编程&#xff08;3&#xff0…

codeforces 1030A-C语言解题报告

题目网址 题目解析 1.输入一串数字,如果有1就输出HARD,否则输出EASY 2.勿忘& 代码 #include<stdio.h> #include<stdlib.h> #include<string.h> int main() {int n0,i0;int num0;int count0;scanf("%d",&n);for(i;i<n;i){scanf(&quo…

C++STL与泛型编程(3)容器之分类与测试

文章目录容器的分类序列式容器&#xff08;sequence containers&#xff09;代码示例辅助函数array 容器array容器的测试代码测试代码中部分函数解析vector 容器vector 容器的测试代码测试代码中部分函数解析list 容器list 容器的测试代码测试代码中部分函数解析forward_list 容…

codeforces 318A-C语言解题报告

题目网址 题目 1.一个数先奇数从小到大再偶数从小到大(1–n),问第k个数是什么? 2.举例发现规律: 第k个数与n的奇偶无关,使用中间数mid(a1)/2;进行判断,k是奇数还是偶数 奇数:countb*2-1; 偶数:count(b-mid)*2; 3.因为数很大,使用scanf("%lld %lld",&a,&…

C++面试题目

C和C的区别 总览 C是一个结构化语言&#xff0c;它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程&#xff0c;对输入&#xff08;或环境条件&#xff09;进行运算处理得到输出&#xff08;或实现过程&#xff08;事务&#xff09;控制&#xff09;。C&…

C++STL与泛型编程(4)OOP(面向对象编程) Vs. GP(泛型编程)

文章目录OOP和GP为什么list不能使用标准库中的::sort算法&#xff1f;采用GP的好处OOP和GP OOP将datas和methods关联在一起 GP将datas和methods分开 为什么list不能使用标准库中的::sort算法&#xff1f; 因为标准库的sort的算法用到了随机访问迭代器&#xff08;RandomAcce…

codeforces 158B-C语言解题报告

题目网址 题目解析 参考博客 代码 #include<iostream> #include<string.h> #include<algorithm> #include<stdio.h> #include<math.h> using namespace std; int n,a[100005]; long long sum,s1,s2,s3;main() {cin>>n;for(int i1;i<…

ECC 公钥加密 使用相同的ECC公钥对 对 相同的数据进行加密,每次的加密结果是一致的吗?

ECC 公钥加密 使用相同的ECC公钥对 对 相同的数据进行加密&#xff0c;每次的加密结果是一致的吗&#xff1f;不一致里面包装了个临时的点&#xff0c;使用这个增加安全性

C++ primer 第7章 类

成员函数的声明必须在类的内部&#xff0c;定义则既可以在类的内部&#xff0c;也可以在类的外部。 作为接口组成部分的非成员函数&#xff0c;它们的定义和声明都在类的外部。 类可以允许其他类或者函数访问它的非公有成员&#xff0c;方法是令其他类或函数成为它的友元。如果…

codeforces 705A-C语言解题报告

题目网址 题目解析 1.重点:结尾是it,中间使用that连接,所以使用for循环,奇数输出I hate,偶数输出I love,i!n时,输出that 代码 #include<stdio.h> #include<stdlib.h> #define SIZE 100000 int main() {int n0;scanf("%d",&n);if(n1){printf(&quo…