看下面例子:

#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++父类指针强制转为子类指针后的测试(帮助理解指针访问成员的本质)(反多态)的更多相关文章

  1. 传入的结构体指针强制转为实例化结构体*v

    struct val *v = (struct val *)arg;//传入的结构体指针强制转为实例化结构体*v struct val{ int num1; int num2; }; void *te ...

  2. c# 父类的引用指向子类的实例

    在C#中关于父类对子类的引用大概有这么几种: 父类是接口,普通类,抽象类 public interface A { void a(); } public class B { public void b ...

  3. C++虚函数表解析(图文并茂,非常清楚)( 任何妄图使用父类指针想调用子类中的未覆盖父类的成员函数的行为都会被编译器视为非法)good

    C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有“多种形态”,这是一种泛型技术 ...

  4. C++析构函数的自动调用(析构函数必须是虚拟的,这样删除父类指针指向的子类对象,才能同时调用两者的析构函数,否则就没有机会调用子类析构函数)

    class A {public: A() { printf("A \n"); } ~A() { printf(" ~A \n"); } // 这里不管写不写vi ...

  5. Java中父类强制转换为子类的可能

    之前徒弟问了一个问题, 在Java中, 父类对象到底能不能转换成对应的子类对象? 到底能不能, 今天就来说说这个问题, 先看下面一段代码: package cn.com.hanbinit.test; ...

  6. c++ 动态判断基类指针指向的子类类型(typeid)

    我们在程序中定义了一个基类,该基类有n个子类,为了方便,我们经常定义一个基类的指针数组,数组中的每一项指向都指向一个子类,那么在程序中我们如何判断这些基类指针是指向哪个子类呢? 本文提供了两种方法 ( ...

  7. Java父类强制转换子类原则

    最近,微信群友在讨论子类父类的转换问题,其实不难,给大家用实例来说明一下就很明了了. 我们知道Java中子类转换成父类是没有任何问题的,那父类可以转换成子类吗? 来看下面这段程序: public cl ...

  8. Qt之美(一):d指针/p指针详解(解释二进制兼容,以及没有D指针就会崩溃的例子。有了D指针,所使用的对象大小永远不会改变,它就是该指针的大小。这个指针就被称作D指针)good

    Translated  by  mznewfacer   2011.11.16 首先,看了Xizhi Zhu 的这篇Qt之美(一):D指针/私有实现,对于很多批评不美的同路人,暂且不去评论,只是想支持 ...

  9. 你好,C++(40)7.1 一切指针都是纸老虎:彻底理解指针

    第7章 C++世界的奇人异事 在武侠小说中,初入武林的毛头小子总是要遇到几位奇人,发生几件异事,经过高人的指点,经历一番磨炼,方能武功精进,从新手成长为高手.在C++世界,同样有诸多的奇人异事.在C+ ...

随机推荐

  1. centos7命令

    查看ip ip addr ip link 添加服务 systemctl enable nginx 添加防火墙端口 firewall-cmd --zone=public --add-port=80/tc ...

  2. echarts折线图--数据交互

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  3. nodeschool.io 7

    ~~ HTTP CLIENT ~~ Write a program that performs an HTTP GET request to a URL provided toyou as the f ...

  4. MyBatis框架Maven资源

      <!-- MyBatis框架 --> <dependency> <groupId>org.mybatis</groupId> <artifac ...

  5. 杂谈:Servlet(2)

    Servlet的方法剖析: 1.service()方法里面做了什么? 2.doGet()与doPost()做了什么?应该怎么写? 回答 1.service()方法里面做了什么? 如果你的service ...

  6. C与C++在const用法上的区别

    首先,C和C++在大体结构上不同,却在语法上相同.  所以在使用的时候,我们会时常遇到一些莫名其妙的问题,觉得语法上是正确的,但是编译的时候却出现一个红色的 error! 比如今天我遇到的这个有意思的 ...

  7. cf(#div1 A. Dreamoon and Sums)(数论)

    A. Dreamoon and Sums time limit per test 1.5 seconds memory limit per test 256 megabytes input stand ...

  8. 128. Longest Consecutive Sequence *HARD* -- 寻找无序数组中最长连续序列的长度

    Given an unsorted array of integers, find the length of the longest consecutive elements sequence. F ...

  9. 把Angular中的$http变成jQuery.ajax()一样,可以让后台(php)轻松接收到参数

    最近接到一个手机项目,我决定用ionic + php + mysql来实现.ionic是一个前端框架,主要用于手机端,它融合了html5.css3.angularJS于一体,用起来很顺手. 开始构建项 ...

  10. 二模 (4) day1

    第一题: 题目描述: 有一个无穷序列如下:110100100010000100000…请你找出这个无穷序列中指定位置上的数字 解题过程: 1.考虑到1的数目比0少的多,就从1的位置的规律开始分析.前几 ...