1、有父子关系的两个类的对象之间能否进行互相转换呢?
答案:由子类对象给父类对象赋值是可以的,俗称大材小用。在赋值的时候会舍弃子类的新增成员,例如:

#include "Student.h"
 class CXiaoStudent : public CStudent
 {
 public:
     int yuwen_score;
     int shuxue_score;
     int english_score;    CXiaoStudent() : CStudent("zhangsan", 'm', 1001, 20)
     {
         yuwen_score = 2;
         shuxue_score = 0;
         english_score = 0;        flag_private = 0;
         flag_protected = 0;
     }private:
     int flag_private;protected:
     int flag_protected;
 };class CZhongStudent : public CXiaoStudent
 {
 public:
     int wuli_score;
     int huaxue_score;    CZhongStudent()
     {
         wuli_score = 0;
         huaxue_score = 0;
     }public:
     int get_flag_1()
     {
         //return flag_private;
         return flag_protected;
     }
 };//赋值操作:
 int main(int argc, char* argv[])
 {
     CZhongStudent zhong_1;
     zhong_1.wuli_score = 90;
     zhong_1.yuwen_score = 100;
     zhong_1.age = 15;    CStudent base_stu = zhong_1; //由子类对象给父类对象赋值
    return 0;
 }

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

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

void average_age(CStudent* p_arr_stud, int n_size)
 {
     if (!p_arr_stud || n_size <= 0) return;    int total_age = 0;
     EStudentType type = p_arr_stud[0].type;
     for (int idx = 0; idx < n_size; ++idx)
     {
         switch (type)
         {
         case EStudentType_Xiao:
             total_age += ((CXiaoStudent*)p_arr_stud)[idx].age;
             break;
         case EStudentType_Zhong:
             total_age += ((CZhongStudent*)p_arr_stud)[idx].age;
             break;
         default:
             break;
         }
     }    int aver_age = total_age / n_size;
     switch (type)
     {
     case EStudentType_Xiao:
         cout << "小学生的平均年龄是:" << aver_age << endl;
         break;
     case EStudentType_Zhong:
         cout << "中学生的平均年龄是:" << aver_age << endl;
         break;
     default:
         break;
     }
 }



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

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

3、小作业,刚刚的 average_age 函数我改成这样行不行?

void average_age(CStudent* p_arr_stud, int n_size)
 {
     int total_age = 0;
     if (!p_arr_stud || n_size <= 0) return;
     for (int idx = 0; idx < n_size; ++idx)
     {
         total_age += p_arr_stud[idx].age;
     }    EStudentType type = p_arr_stud[0].type;
     int aver_age = total_age / n_size;
     switch (type)
     {
     case EStudentType_Xiao:
         cout << "小学生的平均年龄是:" << aver_age << endl;
         break;
     case EStudentType_Zhong:
         cout << "中学生的平均年龄是:" << aver_age << endl;
         break;
     default:
         break;
     }


}

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