c++父类指针强制转为子类指针后的测试(帮助理解指针访问成员的本质)(反多态)
看下面例子:
#include "stdafx.h"
#include <iostream>
class A { //父类
public:
void f() //普通函数
{
std::cout<<"A"<<std::endl;
}
void virtual vf() //虚函数
{
std::cout<<"virtual-A"<<std::endl; }
};
class B : public A //子类
{
public:
void f()
{
std::cout<<"B"<<std::endl;
}
void virtual vf()
{
std::cout<<"virtual-B"<<std::endl;
}
int m; //B类的成员变量
B() //在B类的构造中给成员变量赋值
{
this->m=20;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
A *pa = new A(); //只实例化一个父类的对象,但下面要当作子类用
B *pb = (B *)pa; //用强制类型转换,把父类指针转化为子类指针,用这个子类指针访问子类的成员
pb->f(); //覆盖时,调用的是子类的函数
pb->vf(); //虚函数时,调用的是父类的函数,是因为虚函数表记录的是父类的方法,没有显示new一个子类,所以不会改虚函数表的内容
std::cout<<pb->m<<std::endl; //结果输出的是乱码,不是20
//原因,要输出子类的成员变量m,但实际上pb指向的内存空间只有父类大小,所以访问的m实际上是超出了实例化的对象的范围 return 0;
}
运行结果:

总结:其实可以这样理解,根据某个类型的指针访问某个成员时,编译器会根据类型的定义, 查找这个成员(对编译器来讲成员名只是个标记)所在偏移量,用这个偏移量获取成员。 比如上面用指针pb访问成员变量m时,m对于pb来说只是个标记,说明要从pb开始偏移多少个字节才能访问到m。
上面的例子我称为“反多态”,因为,通过一个多态的指针(多态时是父类型的指针,上面的例子是子类型的指针)访问普通成员函数时访问的是子类的函数(刚好和多态相反),通过子类的指针访问虚函数时访问的是父类的函数(也刚好和多态相反)。
c++父类指针强制转为子类指针后的测试(帮助理解指针访问成员的本质)(反多态)的更多相关文章
- 传入的结构体指针强制转为实例化结构体*v
struct val *v = (struct val *)arg;//传入的结构体指针强制转为实例化结构体*v struct val{ int num1; int num2; }; void *te ...
- c# 父类的引用指向子类的实例
在C#中关于父类对子类的引用大概有这么几种: 父类是接口,普通类,抽象类 public interface A { void a(); } public class B { public void b ...
- C++虚函数表解析(图文并茂,非常清楚)( 任何妄图使用父类指针想调用子类中的未覆盖父类的成员函数的行为都会被编译器视为非法)good
C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有“多种形态”,这是一种泛型技术 ...
- C++析构函数的自动调用(析构函数必须是虚拟的,这样删除父类指针指向的子类对象,才能同时调用两者的析构函数,否则就没有机会调用子类析构函数)
class A {public: A() { printf("A \n"); } ~A() { printf(" ~A \n"); } // 这里不管写不写vi ...
- Java中父类强制转换为子类的可能
之前徒弟问了一个问题, 在Java中, 父类对象到底能不能转换成对应的子类对象? 到底能不能, 今天就来说说这个问题, 先看下面一段代码: package cn.com.hanbinit.test; ...
- c++ 动态判断基类指针指向的子类类型(typeid)
我们在程序中定义了一个基类,该基类有n个子类,为了方便,我们经常定义一个基类的指针数组,数组中的每一项指向都指向一个子类,那么在程序中我们如何判断这些基类指针是指向哪个子类呢? 本文提供了两种方法 ( ...
- Java父类强制转换子类原则
最近,微信群友在讨论子类父类的转换问题,其实不难,给大家用实例来说明一下就很明了了. 我们知道Java中子类转换成父类是没有任何问题的,那父类可以转换成子类吗? 来看下面这段程序: public cl ...
- Qt之美(一):d指针/p指针详解(解释二进制兼容,以及没有D指针就会崩溃的例子。有了D指针,所使用的对象大小永远不会改变,它就是该指针的大小。这个指针就被称作D指针)good
Translated by mznewfacer 2011.11.16 首先,看了Xizhi Zhu 的这篇Qt之美(一):D指针/私有实现,对于很多批评不美的同路人,暂且不去评论,只是想支持 ...
- 你好,C++(40)7.1 一切指针都是纸老虎:彻底理解指针
第7章 C++世界的奇人异事 在武侠小说中,初入武林的毛头小子总是要遇到几位奇人,发生几件异事,经过高人的指点,经历一番磨炼,方能武功精进,从新手成长为高手.在C++世界,同样有诸多的奇人异事.在C+ ...
随机推荐
- Linux下安装最新的Eclipse
欢迎关注我的社交账号: 博客园地址: http://www.cnblogs.com/jiangxinnju/p/4781259.html GitHub地址: https://github.com/ji ...
- JavaScript ——闭包理解
昨天晚上听别人谈起闭包这个东西,虽然对js有一点了解但却丝毫没有印象,今天也没什么事就顺便研究了一下满足好奇宝宝.整合于网上的理解,记录一下. 一.闭包的作用域 要理解闭包,首先必须理解Javascr ...
- 各大互联网公司2014前端笔试面试题–JavaScript篇
很多面试题是我自己面试BAT亲身经历碰到的.整理分享出来希望更多的前端er共同进步吧,不仅适用于求职者,对于巩固复习js更是大有裨益. 而更多的题目是我一路以来收集的,也有往年的,答案不确保一定正确, ...
- Intellij IDEA中配置Maven
maven学习资料:http://www.youmeek.com/intellij-idea-part-xviii-maven/ 待描述...
- Javascript脚本应该放在哪里?
1.<head> <srcipt>在被调用的时候才执行(页面加载前执行)</script> </head> 2. <srcipt>在被调用的 ...
- [BI基础] 一些不得不了解的概念
0.Hadoop hadoop主要是用来对海量数据进行存储和计算的. 它本身是一个分布式系统,核心由分布式文件系统hdfs,和分布式计算框架mapreduce组成,在存储和计算时能够发挥出集群中每台机 ...
- XPath语法 在C#中使用XPath示例 【转http://www.cnblogs.com/yukaizhao/archive/2011/07/25/xpath.html】非常详细的文章
XPath语法 在C#中使用XPath示例 XPath可以快速定位到Xml中的节点或者属性.XPath语法很简单,但是强大够用,它也是使用xslt的基础知识. 示例Xml: <?xml ve ...
- poj----(1470)Closest Common Ancestors(LCA)
Closest Common Ancestors Time Limit: 2000MS Memory Limit: 10000K Total Submissions: 15446 Accept ...
- nyoj------170网络的可靠性
网络的可靠性 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 A公司是全球依靠的互联网解决方案提供商,也是2010年世博会的高级赞助商.它将提供先进的网络协作技术,展 ...
- easyui datagrid导出excel
[第十四篇]easyui datagrid导出excel <a class="btn btn-app" onclick="exportExcel()" ...