C++赋值兼容原则(派生类对象是基类对象,反之不成立)

–基类指针强制转换成派生类指针

–派生类中重定义基类成员(同名覆盖)


假设, 一个基类 "普通人", 一个派生类 "超人".

1) 赋值兼容原则(派生类对象是基类对象,反之不成立)

超人是人吧, 但不是每个人都是超人.
现在我要找一个普通人来干活.
Man* p = new Man; // OK, p指向了一个普通人对象.
Man* p = new SuperMan; // 也OK, 虽然有些大才小用, 但是超人确实可以胜任普通人的工作.
反过来的话.
SuperMan* sp = new Man; // No, 错误, 我需要一个超人, 普通人无法胜任..

2) 基类指针强制转换成派生类指针.

基类指针不可以直接转换成派生指针.
因为你如果准备让普通人(基类)去做超人(派生类)的工作, 是非常危险的, 所以语法不允许.
但是, 由(1)我们知道超人有可能隐藏在普通人之间的(指针是Man*, 但实际对象是SuperMan).
在你确切知道他实际上是超人的时候, 那么可以使用"强制转化", 让他去做超人的事情.
但是, 如果他真的只是普通人, 那么"强制转换"的后果是不确定的, 很可能会引发运行错误.
Man* p = new SuperMan; // 虽然是Man*, 但实际是SuperMan.
((SuperMan*)p)->Fly(); // "强制转换"之后调用 Fly(飞行)函数.
Man* p = new Man; // 真的只是普通人.
((SuperMan*)p)->Fly(); // 语法可以通过, 但是运行阶段很可能会出现莫名其妙的错误.

(3) 派生类中重定义基类成员

成员函数前加virtual表示虚函数, 意味着派生类可能会有自己的特殊实现.
比如说"看"Look这个动作, 普通人只是用肉眼看, 但是超人用红外线看东西.
class Man{ virtual void Look(){ // 正常人看的代码.} };
class SuperMan: public Man{ virtual void Look(){ // 红外线 }};

SuperMan中的Look前面加不加virtual都可以, 意思不会变.
Man* p = new SuperMan;
p->Look() // 红外线, 虽然用Man*调用函数, 但是由于是虚函数, 会自动定位到SuperMan::Look上。

---------------------

参考: https://blog.csdn.net/cs494208907/article/details/11920971

C++赋值兼容原则的更多相关文章

  1. C++赋值兼容原则理解

    –赋值兼容原则(派生类对象是基类对象,反之不成立)–基类指针强制转换成派生类指针–派生类中重定义基类成员(同名覆盖) 假设, 一个基类 "普通人", 一个派生类 "超人& ...

  2. C++虚函数、赋值兼容原则

    #include <iostream.h> class A { public: void f1() { cout << "a" << endl; ...

  3. C++语言笔记系列之十六——赋值兼容规则&amp;多继承的二义性

    1.赋值兼容规则 (1)派生类对象能够给基类对象赋值,这样的情况下派生类对象将从基类继承的成员的值赋值给一个基类对象:可是不同意将一个基类的对象赋值给一个派生类. (2)能够将派生类对象的地址赋给基类 ...

  4. C++:基类与派生类对象之间的赋值兼容关系

    4.5 基类与派生类对象之间的赋值兼容关系 在一定条件下,不同类型的数据之间可以进行类型转换,例如可以将整型数据赋给双精度型变量. 在赋值之前,先把整型数据转换为双精度型数据,然后再把它双精度型变量. ...

  5. 类型兼容原则(C++)

    类型兼容原则是指在需要基类对象的任何地方,都可以使用公有派生类的对象来替代. 通过公有继承,派生类得到了基类中除构造函数.析构函数之外的所有成员.这样,公有派生类实际具备了基类的所有功能,凡是基类能解 ...

  6. C++中的继承详解(3)作用域与重定义,赋值兼容规则

    作用域与同名隐藏 一样的,先上代码 1 class A 2 { 3 public: 4 int a_data; 5 void a() 6 { 7 cout << "A" ...

  7. C++中的继承(3)作用域与重定义,赋值兼容规则

    作用域与重定义(同名隐藏) 一样的,先上代码 1 class A 2 { 3 public: 4 int a_data; 5 void a() 6 { 7 cout << "A& ...

  8. C++中的继承(3)作用域与重定义,赋值兼容规则

    1.作用域与重定义(同名隐藏) 一样的,先上代码 1 class A 2 { 3 public: 4 int a_data; 5 void a() 6 { 7 cout << " ...

  9. C++:同名隐藏和赋值兼容规则

    一.同名隐藏 同名隐藏,即在C++的继承中,只要子类的函数名和父类的函数名相同,子类中的函数将会隐藏所有父类中和子类的成员函数同名的函数 特别注意: 和函数之间的重载不同,这里只要求函数的名字相同,而 ...

随机推荐

  1. 023 SpringMVC拦截器

    一:拦截器的HelloWorld 1.首先自定义拦截器 只要实现接口就行. package com.spring.it.interceptors; import javax.servlet.http. ...

  2. 009 使用servlet API作为参数

    1.哪些可以使用 MVC中的Handler方法可以接受ServletAPI类型的参数. 2.controller package com.spring.it; import java.io.IOExc ...

  3. ADI SHARC 学习之PLL

    PLL Block Diagram             Power Management Registers (PMCTL, PMCTL1)The following sections descr ...

  4. QT学习之第一个程序

    QT学习之第一个程序 目录 手动创建主窗口 居中显示 添加窗口图标 显示提示文本 Message Box的应用 手动连接信号与槽 手动创建主窗口 窗口类型 QMainWindow: 可以包含菜单栏.工 ...

  5. python数据分析之pandas数据选取:df[] df.loc[] df.iloc[] df.ix[] df.at[] df.iat[]

    1 引言 Pandas是作为Python数据分析著名的工具包,提供了多种数据选取的方法,方便实用.本文主要介绍Pandas的几种数据选取的方法. Pandas中,数据主要保存为Dataframe和Se ...

  6. 算法进阶面试题01——KMP算法详解、输出含两次原子串的最短串、判断T1是否包含T2子树、Manacher算法详解、使字符串成为最短回文串

    1.KMP算法详解与应用 子序列:可以连续可以不连续. 子数组/串:要连续 暴力方法:逐个位置比对. KMP:让前面的,指导后面. 概念建设: d的最长前缀与最长后缀的匹配长度为3.(前缀不能到最后一 ...

  7. bzoj5312: 冒险(势能均摊线段树)

    题目链接 BZOJ5312: 冒险 题解 如果一次操作对区间& 和 区间| 产生的影响是相同的,那么该操作对整个区间的影响都是相同的 对于每次操作,在某些位上的值,对于整个区间影响是相同的,对 ...

  8. 4067: [Ctsc2015]gender 动态规划 网络流

    国际惯例的题面:首先这题是缺少两个隐藏条件的:第一个是这k条链的起点和终点所在的层是对齐的,也就是说不会出现两条链错开的情况,且这张图恰好由n层组成:第二个就是任意一个点都包含在与链上的点直接或间接相 ...

  9. php 日期和时间

    php date() 函数把时间戳格式化为更易读取的日期和时间 语法: date(formet,timestamp); 参数 描述 format 必需.规定时间戳的格式. timestamp 可选.规 ...

  10. 通过Microsoft.AspNetCore.App元包简化程序集的引用

    Asp.net core下提供默认提供了一些在.net core不能直接使用的库,如日志.依赖注入.选项.通用主机.EntityFramework等,虽然我们可以通过Nuget的方式手动加载这些包,但 ...