VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 5550|回复: 90

《实用C++》第41课 父类对象与子类对象之间的相互转换

  [复制链接]
51_avatar_middle
online_admins 发表于 2018-5-20 00:44:08 | 显示全部楼层 |阅读模式
1、有父子关系的两个类的对象之间能否进行互相转换呢?
答案:由子类对象给父类对象赋值是可以的,俗称大材小用。在赋值的时候会舍弃子类的新增成员,例如:
  1. #include "Student.h"
  2. class CXiaoStudent : public CStudent
  3. {
  4. public:
  5.     int yuwen_score;
  6.     int shuxue_score;
  7.     int english_score;

  8.     CXiaoStudent() : CStudent("zhangsan", 'm', 1001, 20)
  9.     {
  10.         yuwen_score = 2;
  11.         shuxue_score = 0;
  12.         english_score = 0;

  13.         flag_private = 0;
  14.         flag_protected = 0;
  15.     }

  16. private:
  17.     int flag_private;

  18. protected:
  19.     int flag_protected;
  20. };

  21. class CZhongStudent : public CXiaoStudent
  22. {
  23. public:
  24.     int wuli_score;
  25.     int huaxue_score;

  26.     CZhongStudent()
  27.     {
  28.         wuli_score = 0;
  29.         huaxue_score = 0;
  30.     }

  31. public:
  32.     int get_flag_1()
  33.     {
  34.         //return flag_private;
  35.         return flag_protected;
  36.     }
  37. };
复制代码

  1. //赋值操作:
  2. int main(int argc, char* argv[])
  3. {
  4.     CZhongStudent zhong_1;
  5.     zhong_1.wuli_score = 90;
  6.     zhong_1.yuwen_score = 100;
  7.     zhong_1.age = 15;

  8.     CStudent base_stu = zhong_1; //由子类对象给父类对象赋值

  9.     return 0;
  10. }
复制代码


但是,反过来,由父类的对象给子类的对象赋值是不允许的,会出现填不满的不可预知行为。

2、父子类对象转换的实际用途:
在实际的编程过程中,直接进行父子类的对象的相互转换的情况比较少。一般是使用指针来操作。
上节课最后给大家留了一个小作业:
用一个函数来实现一个功能,分别统计全市在校学生的平均年龄。学生包括小学生、中学生、高中生、大学生 等。用一个函数来实现!
不知道大家思考的怎么样?只能用一个函数来实现,还要自动区分是小学生、中学生、高中生或者大学生?要怎么做呢?接下来教大家一种方法。

  1. void average_age(CStudent* p_arr_stud, int n_size)
  2. {
  3.     if (!p_arr_stud || n_size <= 0) return;

  4.     int total_age = 0;
  5.     EStudentType type = p_arr_stud[0].type;
  6.     for (int idx = 0; idx < n_size; ++idx)
  7.     {
  8.         switch (type)
  9.         {
  10.         case EStudentType_Xiao:
  11.             total_age += ((CXiaoStudent*)p_arr_stud)[idx].age;
  12.             break;
  13.         case EStudentType_Zhong:
  14.             total_age += ((CZhongStudent*)p_arr_stud)[idx].age;
  15.             break;
  16.         default:
  17.             break;
  18.         }
  19.     }

  20.     int aver_age = total_age / n_size;
  21.     switch (type)
  22.     {
  23.     case EStudentType_Xiao:
  24.         cout << "小学生的平均年龄是:" << aver_age << endl;
  25.         break;
  26.     case EStudentType_Zhong:
  27.         cout << "中学生的平均年龄是:" << aver_age << endl;
  28.         break;
  29.     default:
  30.         break;
  31.     }
  32. }
复制代码


说明:这里是统计所有类型学生的信息,学生有多种类型,有小学生、中学生、高中生、大学生 等等。以后还可能统计研究生、博士生等等。所以类型很多,如果你针对每种类型的学生都写一个函数进行统计那就非常麻烦了。所以这块我们只写一个函数,还要把全类型都覆盖了,那么我们只能传递各种学生的父类型的指针,因为从子对象往父对象转换是可以的,就是我们之前说的大材小用。但是由父对象往子对象转换往往很危险。另外我们这里面转换的也只是一个指针类型而已,真正子类型的指针指向的那块内存不会因为把指针类型改成父类型了就改变内存结构了。所以我们先通过参数把各种类型的学生都统一成基本的学生类型,之后在函数内部通过事先在父类中定义好的类型来区分参数传进来的到底是哪种子类型,之后强制类型转换就行了。

有的网友会说,你这个强制类型转换不就是从父类型转换到子类型吗?不是很危险吗?你为什么还这样做?刚刚我说过了,指针指向的那块内存本身就是子类型的,之前只不过用另外一种指针指了一下,不会影响那块的内存结构,也不会修改那块的内存内容,所以在函数中再转回来是一点问题没有的。大家明白了吗?我这个例子中用的方法在以后的编程过程中会时不时的用到的,可以解决不少问题,这个思想还是希望大家掌握哦!

3、小作业,刚刚的 average_age 函数我改成这样行不行?
  1. void average_age(CStudent* p_arr_stud, int n_size)
  2. {
  3.     int total_age = 0;
  4.     if (!p_arr_stud || n_size <= 0) return;
  5.     for (int idx = 0; idx < n_size; ++idx)
  6.     {
  7.         total_age += p_arr_stud[idx].age;
  8.     }

  9.     EStudentType type = p_arr_stud[0].type;
  10.     int aver_age = total_age / n_size;
  11.     switch (type)
  12.     {
  13.     case EStudentType_Xiao:
  14.         cout << "小学生的平均年龄是:" << aver_age << endl;
  15.         break;
  16.     case EStudentType_Zhong:
  17.         cout << "中学生的平均年龄是:" << aver_age << endl;
  18.         break;
  19.     default:
  20.         break;
  21.     }
  22. }
复制代码


代码看着很简洁,不知道结果是否正确,大家不妨先试试,如果结果正确那没什么说的,如果结果不争取,那是为什么呢?为什么会出现这样的情况?还请大家课后仔细想想!


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
教程在线观看地址:
https://www.bilibili.com/video/av38388453/?p=43
MP4高清视频下载地址:链接:https://pan.baidu.com/s/1rBJU34YGCAFM-XNioT3pLA 提取码:006o
本节课件下载(回复后可见):
游客,如果您要查看本帖隐藏内容请回复

备注:VIP会员可免费下载本站所有资源(点击查看)
提示:通过购买VC驿站U盘打包(点击查看)也可加入终身Vip会员^_^




上一篇:《实用C++》第40课 子类的构造函数与析构函数
下一篇:《实用C++》第42课 多态性与虚函数
78_avatar_middle
在线会员 发表于 2018-5-20 08:16:36 | 显示全部楼层
更新好快。谢谢
80_avatar_middle
在线会员 发表于 2018-5-20 08:54:50 | 显示全部楼层
坚持学习!
98_avatar_middle
在线会员 发表于 2018-5-20 10:12:32 | 显示全部楼层
谢谢分享




74_avatar_middle
在线会员 发表于 2018-5-20 13:09:24 | 显示全部楼层
看看         
94_avatar_middle
online_vip 发表于 2018-5-20 23:00:33 | 显示全部楼层
坚持学习!
62_avatar_middle
在线会员 发表于 2018-5-22 09:36:59 | 显示全部楼层
这个更新速度,真实牛《实用C++》第41课 父类对象与子类对象之间的相互转换
09_avatar_middle
online_vip 发表于 2018-5-22 11:58:20 | 显示全部楼层
学习下,补下基础
79_avatar_middle
在线会员 发表于 2018-5-23 14:38:16 | 显示全部楼层
支持支持支持支持支持支持
95_avatar_middle
在线会员 发表于 2018-5-25 00:07:48 | 显示全部楼层
更新好快。谢谢
85_avatar_middle
在线会员 发表于 2018-5-28 08:38:50 | 显示全部楼层
感谢分享,学习一下。
18_avatar_middle
online_vip 发表于 2018-5-28 22:01:06 | 显示全部楼层
学习一下,感谢分享
44_avatar_middle
在线会员 发表于 2018-5-29 09:21:56 | 显示全部楼层
多谢楼主费心录制.
06_avatar_middle
online_vip 发表于 2018-5-29 17:42:48 | 显示全部楼层
我爱学习 学习爱我
96_avatar_middle
在线会员 发表于 2018-5-29 20:36:06 | 显示全部楼层
坚持学习~~~~~
82_avatar_middle
在线会员 发表于 2018-5-31 07:46:58 | 显示全部楼层
强啊。。又出新课
58_avatar_middle
在线会员 发表于 2018-5-31 19:33:00 | 显示全部楼层
谢谢分享!
75_avatar_middle
在线会员 发表于 2018-6-1 18:38:40 | 显示全部楼层
感谢分享,楼主辛苦了!
38_avatar_middle
在线会员 发表于 2018-6-6 21:33:13 | 显示全部楼层
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
11_avatar_middle
在线会员 发表于 2018-6-9 07:13:19 | 显示全部楼层

感谢分享,谢谢。
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号tongdun|网站地图wx_jqr

GMT+8, 2019-9-18 14:19

Powered by Discuz! X3.4

© 2009-2019 cctry.com

快速回复 返回顶部 返回列表