最近在逛B站的时候发现有候捷老师的课程,如获至宝.因此,跟随他的讲解又复习了一遍关于C++的内容,收获也非常的大,对于某些模糊的概念及遗忘的内容又有了更深的认识. 以下内容是关于虚函数表.虚函数指针,而C++中的动态绑定实现和这两个内容是分不开的. 一,虚函数表.虚指针 ​当一个类在实现的时候,如果存在一个或以上的虚函数时,那么这个类便会包含一张虚函数表.而当一个子类继承并重写了基类的虚函数时,它也会有自己的一张虚函数表. 当我们在设计类的时候,如果把某个函数设置成虚函数时,也就表明我们希望子类…
从例子入手,考察如下带有虚函数的类的对象内存模型: class A { public: virtual void vfunc1(); virtual void vfunc2(); void func1(); void func2(); virtual ~A(); private: int m_data1, m_data2; }; class B : A { public: virtual void vfunc1();; void func2(); virtual ~B(); private: i…
class A { public: virtual void vfunc1(); virtual void vfunc2(); void func1(); void func2(); virtual ~A(); private: int m_data1, m_data2; }; class B : A { public: virtual void vfunc1();; void func2(); virtual ~B(); private: int m_data3; }; class C : B…
前导 在上面的博文中描述了基类中存在虚函数时,基类和派生类中虚函数表的结构. 在派生类也定义了虚函数时,函数表又是怎样的结构呢? 先看下面的示例代码: #include <iostream> using namespace std; class A { public: virtual void funcA(){ cout<<"A"<<endl; } }; class B { public: virtual void funcB(){ cout<…
本文转载自:http://blog.51cto.com/9291927/2148695 总结: 一.成员函数的内存为什么不会反映在sizeof运算符上?             成员函数可以被看作是类作用域的全局函数, 不在对象分配的空间里, 只有虚函数才会在类对象里有一个指针, 存放虚函数的地址等相关信息(即虚函数表). 成员函数的地址,编译期就已确定,并静态绑定或动态的绑定在对应的对象上.对象调用成员函数时,编译器可以确定这些函数的地址,并通过传入this指针和其 他参数,完成函数的调用,所…
[摘要] 非常多教材上都有介绍到虚指针.虚函数与虚函数表.有的说类对象共享一个虚函数表,有的说,一个类对象拥有一个虚函数表.还有的说,不管用户声明了多少个类对象,可是,这个VTABLE虚函数表仅仅有一个.也有的在说,每一个具有虚函数的类的对象里面都有一个VPTR虚函数指针,这个指针指向VTABLE的首地址,每一个类的对象都有这么一种指针.今天.我们就来解决问题,同一个类的不同对象,是不是拥有"同样"的虚函数表,这个同样是物理上的同样(内存地址)还是逻辑上的同样(数据结构).本文现详述例…
一.多态 多态性是面向对象程序设计的重要特征之一. 多态性是指发出同样的消息被不同类型的对象接收时有可能导致完全不同的行为. 多态的实现: 函数重载 运算符重载 模板 虚函数 (1).静态绑定与动态绑定 静态绑定 绑定过程出现在编译阶段,在编译期就已确定要调用的函数. 动态绑定 绑定过程工作在程序运行时执行,在程序运行时才确定将要调用的函数. 二.虚函数 虚函数的概念:在基类中冠以关键字 virtual 的成员函数 虚函数的定义: virtual 函数类型 函数名称(参数列表); 如果一个函数在…
在讲多态之前,我们先来说说关于多态的一个基石------类型兼容性原则. 一.背景知识 1.类型兼容性原则 类型兼容规则是指在需要基类对象的任何地方,都可以使用公有派生类的对象来替代.通过公有继承,派生类得到了基类中除构造函数.析构函数之外的所有成员.这样,公有派生类实际就具备了基类的所有功能,凡是基类能解决的问题,公有派生类都可以解决.类型兼容规则中所指的替代包括以下情况: 子类对象可以当作父类对象使用 子类对象可以直接赋值给父类对象 子类对象可以直接初始化父类对象 父类指针可以直接指向子类对…
http://blog.csdn.net/alps1992/article/details/45052403 虚函数 虚函数就是用virtual来修饰的函数.虚函数是实现C++多态的基础. 虚表 每个类都会为自己类的虚函数创建一个表,来存放类内部的虚函数成员. 虚函数表指针 每个类在构造函数里面进行虚表和虚表指针的初始化. 下面看一段代码: // // main.cpp // VirtualTable // // Created by Alps on 15/4/14. // Copyright…
C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有“多种形态”,这是一种泛型技术.所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法.比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议. 虚函数表    对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的…
最近看剑指offer,记录一下 #include <iostream> #include <string> #include <cctype> #include<vector> #include<list> #include<cstring> #include<typeinfo> #include<set> #include<map> #include<deque> #include&l…
虚函数表指针 虚函数表指针随对象走,它发生在对象运行期,当对象创建的时候,虚函数表表指针位于该对象所在内存的最前面. 使用虚函数时,虚函数表指针指向虚函数表中的函数地址即可实现多态. 虚函数表 虚函数表是在编译期间就已经确定,且虚函数表存放虚函数的地址也是在创建时被确定. 扩展 虚函数表属于类,类的所有对象共享这个类的虚函数表. 虚函数表由编译器在编译时生成,保存在exe的(常量区).rdata只读数据段. 参考 here…
静态多态.动态多态 静态多态:程序在编译阶段就可以确定调用哪个函数.这种情况叫做静态多态.比如重载,编译器根据传递给函数的参数和函数名决定具体要使用哪一个函数.动态多态:在运行期间才可以确定最终调用的函数.需要通过虚函数+封装+继承实现. 虚函数 虚函数都必须有定义 虚函数一般用在继承中.多个子类继承同一基类,若在某种行为上不同的派生类有着自己的实现方式.这种情况我们就会用到多态.采用在基类中将此函数定义成虚函数,派生类中定义这个函数的不同实现.当我们使用基类的引用或指针调用一个虚成员函数时会执…
http://www.cnblogs.com/DylanWind/archive/2009/01/12/1373919.html 前部分原创,转载请注明出处,谢谢! class Base  {  public:   int m_base;  };  class DerivedA: public Base  {  public:   int m_derivedA;  };  class DerivedB: public Base  {  public:   int m_derivedB;  }; …
一.背景知识(一些基本概念) 虚函数(Virtual Function):在基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数.纯虚函数(Pure Virtual Function):基类中没有实现体的虚函数称为纯虚函数(有纯虚函数的基类称为虚基类).C++  “虚函数”的存在是为了实现面向对象中的“多态”,即父类类别的指针(或者引用)指向其子类的实例,然后通过父类的指针(或者引用)调用实际子类的成员函数.通过动态赋值,实现调用不同的子类的成员函数(动态绑定).正是因为这种…
一.背景知识(一些基本概念) 虚函数(Virtual Function):在基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数. 纯虚函数(Pure Virtual Function):基类中没有实现体的虚函数称为纯虚函数(有纯虚函数的基类称为虚基类). C++ “虚函数”的存在是为了实现面向对象中的“多态”,即父类类别的指针(或者引用)指向其子类的实例,然后通过父类的指针(或者引用)调用实际子类的成员函 数.通过动态赋值,实现调用不同的子类的成员函数(动态绑定).正是因为…
关键词:虚函数.虚表,虚表指针,动态绑定,多态 一.概述 为了实现C++的多态,C++使用了一种动态绑定的技术. 这个技术的核心是虚函数表(下文简称虚表).本文介绍虚函数表是怎样实现动态绑定的. 二.类的虚表 每一个包括了虚函数的类都包括一个虚表. 我们知道,当一个类(A)继承还有一个类(B)时.类A会继承类B的函数的调用权.所以假设一个基类包括了虚函数,那么其继承类也可调用这些虚函数,换句话说,一个类继承了包括虚函数的基类.那么这个类也拥有自己的虚表. 我们来看下面的代码. 类A包括虚函数vf…
//虚基类:一个类可以在一个类族中既被用作虚基类,也被用作非虚基类. class Base1{ public: Base1(){cout<<"Construct Base1!"<<endl;}; void foo();//普通函数 virtual void foo1(){cout<<"foo1 in Base1"<<endl;};//虚函数:可以在基类中实现(+{})或者直接定义成虚基类,\ 会出现错误:undefin…
   C++面试经常会被问的问题就是多态原理.如果对C++面向对象本质理解不是特别好,问到这里就会崩. 下面从基本到原理,详细说说多态的实现:虚函数 & 虚函数表.   1. 多态的本质: 形式上,使用统一的父类指针做一般性处理.但是实际执行时,这个指针可能指向子类对象. 形式上,原本调用父类的方法,但是实际上会调用子类的同名方法. 坦白的说,多态就是为了通过使用父类的指针,能够调用父类与子类他们各自的方法.如果不使用多态,用父类指针调用子类的方法时,也会调用到父类的方法. 具体参考:C++ 虚…
转载:陈皓 http://blog.csdn.net/haoel 前言 C++中 的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术 可以让父类的指针有“多种形态”,这是一种泛型技术.所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法.比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议. 关于虚函数的使用方法,我在这里不做过多的阐述.大家可以看看相关的C…
1.非virtual函数,调用规则取决于对象的显式类型.例如 A* a  = new B(); a->display(); 调用的就是A类中定义的display().和对象本体是B无关系. 2.virtual函数,具体调用哪个版本,取决于虚函数表.例如 A* a = new B(); a->v_display(); 这个时候,对象a就需要查找自身的虚函数表,表中的v_display()是一个函数指针,可能指向不同类中的对应的v_display函数并调用对应版本的v_display.一般而言,如…
先看一个题目: class Base { public: virtual void Show(int x) { cout << "In Base class, int x = " << x << endl; } }; class Derived : public Base { public: virtual void Show(float x) { cout << "In Derived, float x = " &l…
今天翻看陈皓大大的博客,直接找关于C++的东东,看到了虚函数表的内容,找一些能看得懂的地方记下笔记. 0 引子 类中存在虚函数,就会存在虚函数表,在vs2015的实现中,它存在于类的头部. 假设有如下类: class Base { public: virtual void f() { cout << "Base::f" << endl; } virtual void g() { cout << "Base::g" <<…
问题: 包含一个以上虚函数的 class B, 它所定义的 对象是否共用一个虚函数表? 分析: 由于含有虚函数,因此对象内存包含了一个指向虚函数表的指针,但是这个指针指向的是同一个虚函数表吗? 实验如下: 结论: 结果表面,同一个类的所有对象,都共享同一个虚函数表. 派生问题: 派生类 和 基类是否共享同一个虚函数表呢?…
大家知道虚函数是通过一张虚函数表来实现的.在这个表中,主要是一个类的虚函数的地址表,这张表解决了继承.覆盖的问题,其内容真是反应实际的函数.这样,在有虚函数的类的实例中,这个表分配在了这个实例的内存中,所以,当用父类的指针来操作一个子类的时候,这张虚函数表就显得尤为重要了.它就像一个地图一样,指明了实际所应该调用的函数. C++的标准规则中说到,编译器必须保证虚函数表的指针存在于对象实例中最前面的位置(这样是为了保证正确取到虚函数的偏移量).这意味着通过对象实例的地址得到这张虚函数表,然后可以遍…
虚函数表是C++类中存放虚函数的一张表,理解虚函数表对于理解多态很重要. 本次使用的编译器是VS2013,为了简化操作,不用去操作函数指针,我使用到了VS的CL编译选项来查看类的内存布局. CL使用方法: (1)在开始菜单中的vs目录下打开"Visual Studio Tools"目录,找到"VS2013 开发人员命令提示",打开它: (2)将你要编译的文件放到该命令行对应的文件夹中. (3)输入cl "文件名" /d1reportSingleC…
多态性可分为两类:静态多态和动态多态.函数重载和运算符重载实现的多态属于静态多态,动态多态性是通过虚函数实现的. 每个含有虚函数的类有一张虚函数表(vtbl),表中每一项是一个虚函数的地址, 也就是说,虚函数表的每一项是一个虚函数的指针. 没有虚函数的C++类,是不会有虚函数表的. 两张图: 简单例子: 1 #include <iostream> 2 #include <windows.h> 3 4 using namespace std; 5 6 class base 7 { 8…
这里的例子全部来自陈皓的C++ 虚函数表解析,经过修改的. 编译器:g++ (Ubuntu 4.9.2-10ubuntu13) 4.9.2 环境:ubuntu 15.04  64位系统(地址占8字节) 例子1: #define LL long long class Base { public: virtual void f() { cout << "Base::f" << endl; } virtual void g() { cout << &quo…
今天拜读了陈皓的C++ 虚函数表解析的文章,感觉对C++的继承和多态又有了点认识,这里写下自己的理解.如果哪里不对的,欢迎指正.如果对于C++虚函数表还没了解的话,请先拜读下陈皓的C++ 虚函数表解析的文章,不然我写的可能你看不懂. 以前一直对于c++多态感觉很神奇,从书上看,多态就是在构造子类对象的时候,通过虚函数,利用父类指针,来调用子类真正的函数.这个解释是正确的,但是它是怎么实现的呢,一直再猜想.以前也知道有虚函数表这件事,也没有仔细理解是什么东东.今天仔细读了陈皓的文章,才明白C++多…
C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指 向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有“多种形态”,这是一种泛型技术.所谓泛型技术,说白了就是试图 使用不变的代码来实现可变的算法.比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议. 对C++了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的.简称为V-T…