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++赋值兼容原则理解的更多相关文章
- C++赋值兼容原则
C++赋值兼容原则(派生类对象是基类对象,反之不成立) –基类指针强制转换成派生类指针 –派生类中重定义基类成员(同名覆盖) 假设, 一个基类 "普通人", 一个派生类 " ...
- C++虚函数、赋值兼容原则
#include <iostream.h> class A { public: void f1() { cout << "a" << endl; ...
- C++语言笔记系列之十六——赋值兼容规则&多继承的二义性
1.赋值兼容规则 (1)派生类对象能够给基类对象赋值,这样的情况下派生类对象将从基类继承的成员的值赋值给一个基类对象:可是不同意将一个基类的对象赋值给一个派生类. (2)能够将派生类对象的地址赋给基类 ...
- js赋值运算的理解
简介 js引擎由于为了效率,很多时候的非直接量赋值都不是copy一份在赋值给新的变量,而是一个引用 ps:直接量:直接值数字字符串等 为什么使用len = doms.length; 里的len效率要比 ...
- C++:基类与派生类对象之间的赋值兼容关系
4.5 基类与派生类对象之间的赋值兼容关系 在一定条件下,不同类型的数据之间可以进行类型转换,例如可以将整型数据赋给双精度型变量. 在赋值之前,先把整型数据转换为双精度型数据,然后再把它双精度型变量. ...
- 类型兼容原则(C++)
类型兼容原则是指在需要基类对象的任何地方,都可以使用公有派生类的对象来替代. 通过公有继承,派生类得到了基类中除构造函数.析构函数之外的所有成员.这样,公有派生类实际具备了基类的所有功能,凡是基类能解 ...
- C++中的继承详解(3)作用域与重定义,赋值兼容规则
作用域与同名隐藏 一样的,先上代码 1 class A 2 { 3 public: 4 int a_data; 5 void a() 6 { 7 cout << "A" ...
- C++中的继承(3)作用域与重定义,赋值兼容规则
作用域与重定义(同名隐藏) 一样的,先上代码 1 class A 2 { 3 public: 4 int a_data; 5 void a() 6 { 7 cout << "A& ...
- C++中的继承(3)作用域与重定义,赋值兼容规则
1.作用域与重定义(同名隐藏) 一样的,先上代码 1 class A 2 { 3 public: 4 int a_data; 5 void a() 6 { 7 cout << " ...
随机推荐
- 焦大:seo思维光年(上)检索的价值观
http://www.wocaoseo.com/thread-55-1-1.html 检索的价值观是什么?最近很多人咨询我这个问题,因为在百度上根本找不到相关的资料,其实这个东西也是我自己总结的,比如 ...
- 【原创】探索容器底层知识之Namespace
一.先谈谈进程 在正式介绍Namespace之前,先介绍下进程,因为容器本质上是进程,但是在介绍进程之前,先理清下“程序”和“进程”的关系,这是IT从业人员在日常工作中经常碰到的两个词汇,举个通俗点的 ...
- express-session中的saveUninitialized和resave
app.use(session({ name: config.session.name, secret: config.session.secret, resave: true, saveUninit ...
- [ASP.NET Core开发实战]基础篇04 主机
主机定义 主机是封闭应用资源的对象. 设置主机 主机通常由 Program 类中的代码配置.生成和运行. HTTP项目(ASP.NET Core项目)创建泛型主机: public class Prog ...
- 如何用python制作贪吃蛇以及AI版贪吃蛇
用python制作普通贪吃蛇 哈喽,大家不知道是上午好还是中午好还是下午好还是晚上好! 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很 ...
- Android开发之ListView详解 以及简单的listView优化
ListView列表视图 最常用的控件之一,使用场景例如:微信,手机QQ等等. android:divider:每个item之间的分割线,可以使用图片或者色值. android:dividerHeig ...
- Spine学习三 - 同时播放两个动画
这个效果和 Unity的动画分层有点儿像,比如 一个人有一个跑的动画,还有一个站在原地挥手的动画,Unity可以通过动画分层,让人物只需要使用这两个动画实现边跑边挥手的动画效果. 首先介绍一下Spin ...
- 填坑 | .NET core项目远程部署后连接数据库 mysql表大小写敏感问题
欣喜成功部署了项目之后又遭遇重创hhh,swagger调试数据库,报错 MySql.Data.MySqlClient.MySqlException(0x80004005) 我猜是大小写的问题,一查果然 ...
- SpringMVC实例及注解(二)
@RequestMapping()除了修饰方法,还可以修饰类1.类定义处:提供初步的请求映射信息.相对于WEB应用的根目录2.方法处:提供进一步的细分映射信息.相对于类定义处的URL.若类定义处未标注 ...
- Linux 用户与权限
这些天一直在看Linux的命令但是却没有写文章,因为感觉没有必要,哪些简单的命令,vi cat cd 啥的,是个做开发的就知道,所以就没写; 用户管理 第一个我们知道的用户就是Root 没错哦,这就是 ...