linuxsir首页 LinuxSir.Org | Linux、BSD、Solaris、Unix | 开源传万世,因有我参与欢迎您!
网站首页 | 设为首页 | 加入收藏
您所在的位置:主页 > Linux基础建设 >

C++ 基类指针和派生类指针之间的转换

时间:2019-05-14  来源:未知  作者:admin666

函数重载、函数隐藏、函数覆盖

函数重载只会发生在同作用域中(或同一个类中),函数名称相同,但参数类型或参数个数不同。 函数重载不能通过函数的返回类型来区分,因为在函数返回之前我们并不知道函数的返回类型。

函数隐藏和函数覆盖只会发生在基类和派生类之间

函数隐藏是指派生类中函数与基类中的函数同名,但是这个函数在基类中并没有被定义为虚函数,这种情况就是函数的隐藏
所谓隐藏是指使用常规的调用方法,派生类对象访问这个函数时,会优先访问派生类中的这个函数,基类中的这个函数对派生类对象来说是隐藏起来的。 但是隐藏并不意味这不存在或完全不可访问。通过 b->Base::func()访问基类中被隐藏的函数。

函数覆盖特指由基类中定义的虚函数引发的一种多态现象。在某基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数,用法格式为:virtual 函数返回类型 函数名(参数表) {函数体};实现多态性,通过指向派生类的基类指针或引用,访问派生类中同名覆盖成员函数。

函数覆盖的条件:

  • 1: 基类中的成员函数被virtual关键字声明为虚函数;
  • 2:派生类中该函数必须和基类中函数的名称、参数类型和个数等完全一致;
  • 3:将派生类的对象赋给基类指针或者引用,实现多态。

函数覆盖(多态)实现了一种基类访问(不同)派生类的方法。我们把它称为基类的逆袭。

基类指针和派生类指针之间的转换

1. 基类指针指向基类对象、派生类指针指向派生类对象
这种情况是常用的,只需要通过对应类的指针直接调用对应类的功能就可以了。

#include<iostream>
using namespace std;

class Father{
public:    
    void print()
    {
        printf("Father's function!");
    }
};

class Son:public Father
{
public:
    void print()
    {
        printf("Son's function!");
    }
};

int main()
{
    Father f1;
    Son s1;

    Father* f = &f1;
    Son* s = &s1;

    f->print();
    cout<<endl<<endl;
    s->print();
}

2. 基类指针指向派生类对象

这种情况是允许的,通过定义一个基类指针和一个派生类对象,把基类指针指向派生类对象,但是需要注意,通常情况这时的指针调用的是基类的成员函数。分四种情况:

    一、 函数在基类和派生类中都存在

这时通过“指向派生类对象的基类指针”调用成员函数,调用的是基类的成员函数。

   Father f1;
   Son s1;

   Father* f = &s1;
   f->print();  //调用的是基类成员函数

    二、函数在基类中不存在,在派生类中存在

由于调用的还是基类中的成员函数,试图通过基类指针调用派生类才有的成员函数,则编译器会报错。

error C2039: “xxx”: 不是“Father”的成员

      三、 将基类指针强制转换为派生类指针

这种是向下的强制类型转换,转换之后“指向派生类的基类指针”就可以访问派生类的成员函数:

    Son s1;
   Father* f = &s1;
   Son *s = (Son*)f;
   s->print1(); //调用派生类成员函数

但是这种强制转换操作是一种潜在的危险操作

      四、基类中存在虚函数的情况

如果基类中的成员函数被定义为虚函数,并且在派生类中也实现了该函数,则通过“指向派生类的基类指针” 访问虚函数,访问的是派生类中的实现。允许“基类指针指向派生类”这个操作,最大的意义也就在此,通过虚函数和函数覆盖,实现了“多态”(指向不同的派生类,实现不同功能)。

    Father f1;
   Son s1;

   Father* f = &s1;
   f->print();  //调用派生类成员函数

3. 派生类指针指向基类对象

会产生编译错误。基类对象无法被当作派生类对象,派生类中可能具有只有派生类才有的成员或成员函数。
即便是使用强制转换,将派生类指针强制转换成基类指针,通过这个“强制指向基类的派生类指针”访问的函数依然是派生类的成员函数。

   Father f1;
   Son s1;

   Son* s=&s1;
   Father* f = (Father*) s;

   f->print();  //调用派生类成员函数

Linux公社的RSS地址:https://www.linuxidc.com/rssFeed.aspx

友情链接
  • WSL Arch Linux已正式登陆Microsoft Store应用商店
  • GNU调试器 GDB 8.3 发布及安装更新,支持RISC
  • OpenMandriva Lx 4.0将Python 2排除在其基本操作系统之外
  • Linux 5.1.1 发布,几个修复
  • Wine
  • Android Studio 3.5 Beta 发布,性能优化改进
  • Firefox和GNOME最终可以在Linux 5.2的AFS文件系统上运行
  • DifferentialEquations.jl v6.4.0 发布,用于微分方程高性能求解
  • RHEL 8发布后,用户等待CentOS 8的推出
  • Libinput 1.13.2 发布,为苹果TouchPad提供更好的手指检测功能
  • GTK 3.96 发布,作为向GTK 4.0迈进的又一步
  • Phoronix Test Suite v8.8.0m3 发布,开源基准测试
  • CentOS 8.0作为Red Hat Enterprise Linux 8.0社区版重新构建的进
  • GNOME 3.32.2桌面环境发布,最新的bug和安全修复
  • LWJGL 3.2.2 发布,针对Vulkan 1.1和其他新包的更新
  • Mesa 19.0.4 发布,许多RADV, RadeonSI和Intel修复
  • Krita 4.2 Alpha带来性能改进,其他数字绘画增强功能
  • 英特尔为BFloat16添加GCC 10和LLVM Clang 9编译器支持
  • ZFS On Linux 0.8
  • 适用于Ubuntu手机的Ubuntu Touch OTA
  • Kaidan作为Jabber/XMPP聊天客户端加入KDE
  • Google在Chrome中发布新的Cookie控件,改善用户隐私
  • 微软开源PowerToys,计划推出Windows 10版本
  • Linux内核将很快默认情况启用“
  • 由于证书问题,Mozilla延迟Firefox 67推出
  • Radeon ROCm 2.4 发布,兼容TensorFlow 2.0
  • Wine 4.8采用Unicode 12.0更新,更好地支持操纵杆
  • Google宣布Kotlin为Android应用程序开发的首选语言
  • 面向Windows 10的Chromium Microsoft Edge Beta泄露
  • KDE Plasma 5.16推出重写的通知系统
  • 币安交易所被黑客入侵,超过7000比特币被盗
  • Vivaldi 2.5 发布,世界上第一个与Razer Chroma集成的Web浏览器
  • Debian 10 “Buster” 目前在GNOME默认使用Wayland,但仍有可能
  • Linux 5.2中的XFS获得“大量新东西”
  • Firefox 66.0.5发布,包含针对扩展Bug的更多修复
  • Unity 2019.2 Beta 发布,带来许多Linux和Vulkan补丁
  • qBittorrent 4.1.6发布! 如何在Ubuntu 18.04中安装它
  • Linux新闻 第971页
  • MongoDB 日志切割三种方式
  • MongoDB Oplog深入理解
  • MongoDB 副本集搭建与管理详解
  • MongoDB 备份与还原 mongodump、mongorestore
  • MongoDB 常用的几大GUI工具
  • 微软开源Xamarin API Docs
  • Chrome浏览器将不再允许网站劫持后退按钮
  • 福彩3d试机号查询
  • 彩票平台
  • 福彩3d开奖直播
  • 凤凰时时彩平台网址
  • 温岭六家统记牌器