• 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。

    上面的例子我称为“反多态”,因为,通过一个多态的指针(多态时是父类型的指针,上面的例子是子类型的指针)访问普通成员函数时访问的是子类的函数(刚好和多态相反),通过子类的指针访问虚函数时访问的是父类的函数(也刚好和多态相反)。

  • 相关阅读:
    CentOS安装部署Nodejs
    CentOS安装部署Git
    CentOS安装部署Mysql 5.7
    CentOS 7 安装Java环境(脚本一键式安装)
    Java技术 | 细谈Java中UUID的简单了解与使用
    Navicat Premium 版本 12.1 激活成永久
    Java技术 | 细谈 Java 8 中的 Base64
    安装部署Elastic Search
    从零开始搭建linux下laravel 5.5所需环境(二)
    从零开始搭建linux下laravel 5.5所需环境(一)
  • 原文地址:https://www.cnblogs.com/hnfxs/p/3192933.html
Copyright © 2020-2023  润新知