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. 【spring基础】spring与jdbc整合详解

    先上一段简单示例 public class MyTemplate { private DataSource dataSource; public DataSource getDataSource() ...

  2. Strom在本地运行调试出现的错误

    1.错误日志 31385 [main] WARN backtype.storm.daemon.nimbus - Topology submission exception. (topology nam ...

  3. 用户设置与virtual host配置

    1.进入localhost:15672yemian 然后选择Admin菜单. 2.添加用户 caojun/123456 3.效果 4.virtual hosts添加 相当于db. /cjhost,一般 ...

  4. maven在windows下的安装

    1.下载 2.解压 3.修改配置环境 4.验证 5.使用mvn help:system就可以看到下载到本地仓库的文件 6.全局settings 7.建议在m2下拷贝一份属于个人的配置settings

  5. 今天刚学到truncate和delete的区别,做个总结吧

    truncate table : 删除内容,释放空间(表中数据会被删除,但不会进入oracle回收站,直接删除),不删除定义 delete table : 删除内容,不释放空间(表中数据虽被删除,但是 ...

  6. pandas学习(创建数据,基本操作)

    pandas学习(一) Pandas基本数据结构 Series类型数据 Dataframe类型 基本操作 Pandas基本数据结构 两种常用数据结构: Series 一维数组,与Numpy中的一维ar ...

  7. Flutter中打造多行列列表GridView组件的使用

    GridView组件.一个可滚动的二维空间数组. 在使用无限加载滚动列表的时候,最先使用的还是ListView组件.但若是要一行显示2列或者更多列的滚动列表,GridView组件更为方便.如下 在向服 ...

  8. scss、less 对浏览器兼容的处理方法, css 的单行溢出、多行溢出

    1. scss @mixin rounded($param1,$param2) {    #{$param1}:$param2;    -webkit-#{$param1}: $param2;     ...

  9. BZOJ.3531.旅行(树链剖分 动态开点)

    题目链接 无优化版本(170行): /* 首先树剖可以维护树上的链Sum.Max 可以对每个宗教建一棵线段树,那这题就很好做了 不过10^5需要动态开点 (不明白为什么nlogn不需要回收就可以 不是 ...

  10. 洛谷.1501.[国家集训队]Tree II(LCT)

    题目链接 日常zz被define里没取模坑 //标记下放同线段树 注意51061^2 > 2147483647,要开unsigned int //*sz[]别忘了.. #include < ...