实例解析C++虚表

OS:Windows 7

关键字:VS2012,C++,VTable,虚表

1.创建一个Win32控制台应用程序代码如下:

#include "stdafx.h"
#include <string>
#include <iostream>

class A
{
public:
    virtual std::string AName(){return "A";}
};

class B
{
public:
    virtual std::string BName(){return "B";}
};

class C : public A, public B
{
public:
    virtual std::string BName(){return "C";}
};

int _tmain(int argc, _TCHAR* argv[])
{
    C* pC = new C();
    C* pC1 = new C();
    std::cout<<pC->BName()<<std::endl;
    B* pB = static_cast<B*>(pC);
    std::cout<<pB->BName()<<std::endl;
    //A* pA = static_cast<A*>(pB);
    A* pA = dynamic_cast<A*>(pB);
    std::cout<<pA->AName()<<std::endl;
    A* pA1 = reinterpret_cast<A*>(pB);
    std::cout<<pA1->AName()<<std::endl;
    return 0;
}

2.编译运行,控制台输出结果如下:

C

C

A

C

看到这个结果有没有让你奇怪的地方?为什么“pA1->AName()”输出是C?

3.在Watch窗口里看到的虚表结构如下:

总结如下:

  • pC和pC1是类C的两个实例指针,这两个实例的虚表是一样的,也就是说虚表是属于类的,一个类有一个虚表。
  • 因为类C重写了类B的BName函数,所以C的虚表里存的是C::BName
  • “A* pA = static_cast<A*>(pB);”是编译不通过的,因为A和B是不相关的两个类,也就是没有继承关系。
  • “A* pA = dynamic_cast<A*>(pB);”是可以的,因为dynamic_cast会在运行时进行类型检查,dynamic_cast是最安全的,但是效率最低。
  • “A* pA1 = reinterpret_cast<A*>(pB);”是可以编译通过了,但是运行时会有意想不到的结果。reinterpret_cast进行了强制类型转换,但是不会纠正虚表。
时间: 2024-10-21 15:21:45

实例解析C++虚表的相关文章

搭建NFS文件共享--实例解析

1 NFS简介 NFS 是Network File System的缩写,即网络文件系统.一种使用于分散式文件系统的协定,由Sun公 司开发,于1984年向外公布.功能是通过网络让不同的机器.不同的操作系统能够彼此分享个别的数据, 让应用程序在客户端通过网络访问位于服务器磁盘中的数据,是实现磁盘文件共享的一种方法. NFS 的基本原则是"容许不同的客户端及服务端通过一组RPC分享相同的文件系统",它是独立于操作 系统,容许不同硬件及操作系统的系统共同进行文件的分享. 2 NFS服务器的配

第7章 Android HAL实例解析

第7章 Android HAL实例解析 通过本章介绍Android的HAL知道HAL是为了一些硬件提供商提出的保护专利的驱动程序而产生的,是为了避开Linux的GPL束缚.HAL主要的存储目录有:1.libhardware_legany  2.libhardware:3.ril   4.msm7k.主要包含以下一些模块:Gps.Vibrator.Wifi.Copybit.Audio.Camera.Lights.Ril.Overlay等.大概了解了Android  HAL. 第1中方法 直接调用s

基于Android2.3.5系统:JNI与HAL实例解析[一]

*************************************************************************************************************************** 作者:EasyWave                                                                                                           时间:2015.

ASP连接sql server实例解析

1.首先确定自己的iis没有问题 2.其次确定自己sqlserver没有问题 然后在iis的文件夹wwwroot里,建立一个文件 名为testSqlServer.asp,编写代码例如以下就可以 <% 'ole db连接 set cnn1 = Server.CreateObject("ADODB.Connection") '连接串需要注意sqlserver的实例名,是否是默认,非默认必需要写出来 cnn1.Open "provider=sqloledb;data sour

Android开发之UI更新交互机制与实例解析

android开发过程中,经常需要更新UI的状态和文案等.这是就需要对UI进行 更新.在android中更新UI一般有三种方法,handler机制.RunOnUiThread方法以及AsyncTask异步类方法等 本文下面就这三种方法进行了演示和代码实现. a.Handler机制通过使用消息机制来实现 b.RunOnUiThread方法是通过运行UI线程来达到更新UI的目的 c.AsyncTask是异步类,通过异步更新来更新UI 效果图如下:           (1)Java功能实现代码如下:

深入浅出实例解析linux内核container_of宏

做一件事情首先应该知道它的目的是什么. container_of的目的:如何通过结构中的某个变量获取结构本身的指针. 总体思路:假想一下,你的结构体中有好几个成员,你如何通过里面的"任一成员"获取整个结构体的首地址呢.container_of的做法就是通过typeof定义一个与"任一成员"同类型的指针变量pvar_a(假设变量名就是pvar_a),并让指针变量pvar_a指向这个"任一成员",然后用 "pvar_a的地址" 减

jQuery CSS()方法改变CSS样式实例解析

转自:http://www.jbxue.com/article/24588.html 分享一个jQuery入门实例:使用CSS()方法改变现有的CSS样式表,css()方法在使用上具有多样性.其中有一种可接受两个输入参数:样式属性和样式值,两者之间用逗号分隔.比如要改变链接颜色,可以这样编写代码: $("#61dh a").css('color','#123456');//选择器‘$("#61dh a")'表示ID为‘#61dh'的元素下的所有链接.//.css(‘

Android开发之IPC进程间通信-AIDL介绍及实例解析

一.IPC进程间通信 IPC是进程间通信方法的统称,Linux IPC包括以下方法,Android的进程间通信主要采用是哪些方法呢? 1. 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信:   2. 信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身:linux除了支持Unix早期

Nhibernate系列学习之(一) ORM and Nhibernate入门实例解析

最近框架项目需要,数据层想使用Nhibernate,代替传统的sql语句的写法,更加使用面向对象的思维来维护实体与数据库的这层关系映射(ORM),好在之前接触过Java时学习使用了Hibernate,先来了解ORM.    什么是ORM? 对象-关系映射(Object/Relation Mapping,简称ORM),是随着面向对象的软件开发方法发展而产生的.面向对象的开发方法是当今企业级应用开发环境中的主流开发方法,关系数据库是企业级应用环境中永久存放数据的主流数据存储系统.对象和关系数据是业务