• C++ 基类指针和子类指针相互赋值


    首先,给出基类animal和子类fish

    1. //==============================================================  
    2. //           animal.h  
    3. //  
    4. // begin   : 2012-06-30  
    5. // author  : zwq  
    6. // describe: 非虚函数情况下,将子类指针赋给积累指针,验证最终调用  
    7. //           基类函数还是子类函数。  
    8. //==============================================================  
    9. #ifndef ANIMAL_H  
    10. #define ANIMAL_H  
    11.   
    12. //===============================================================  
    13. //  
    14. //                animal  
    15. //               动物基类  
    16. //  
    17. //===============================================================  
    18. class animal  
    19. {  
    20. public:  
    21.     void breathe();     // 非虚函数  
    22. };  
    23.   
    24. //===============================================================  
    25. //  
    26. //                     animal  
    27. //               鱼类,集成于动物基类  
    28. //  
    29. //===============================================================  
    30. class fish : public animal  
    31. {  
    32. public:  
    33.     void breathe();     // 非虚函数  
    34. };  
    35.   
    36. #endif  
    1. #include "StdAfx.h"  
    2. #include <iostream>  
    3. #include "Animal.h"  
    4.   
    5. using namespace std;  
    6.   
    7. //===============================================================  
    8. //  
    9. //                animal  
    10. //               动物基类  
    11. //  
    12. //===============================================================  
    13.   
    14. void animal::breathe()  
    15. {  
    16.     cout << "animal breathe" << endl;  
    17. }  
    18.   
    19. //===============================================================  
    20. //  
    21. //                     animal  
    22. //               鱼类,集成于动物基类  
    23. //  
    24. //===============================================================  
    25.   
    26. void fish::breathe()  
    27. {  
    28.     cout << "fish bubble" << endl;  
    29. }  



    一.基类指针和子类指针之间相互赋值
    (1)将子类指针赋值给基类指针时,不需要进行强制类型转换,C++编译器将自动进行类型转换。因为子类对象也是一个基类对象。

    (2)将基类指针赋值给子类指针时,需要进行强制类型转换,C++编译器将不自动进行类型转换。因为基类对象不是一个子类对象。子类对象的自增部分是基类不具有的。
    执行以下代码,看看会报什么错误:

    1. int main(int argc, char* argv[])  
    2. {  
    3.     ExamAnimal();  
    4.   
    5.     return 0;  
    6. }  
    7.   
    8. void ExamAnimal()  
    9. {  
    10.     // 将子类指针直接赋给基类指针,不需要强制转换,C++编译器自动进行类型转换  
    11.     // 因为fish对象也是一个animal对象  
    12.     animal* pAn;  
    13.     fish* pfh = new fish;  
    14.     pAn = pfh;  
    15.       
    16.     delete pfh;  
    17.     pfh = NULL;  
    18.       
    19.     // 将基类指针直接赋给子类指针,需要强制转换,C++编译器不会自动进行类型转换  
    20.     // 因为animal对象不是一个fish对象  
    21.     fish* fh1;  
    22.     animal* an1 = new animal;  
    23.     // 没有进行强制类型转化  
    24.     fh1 = an1;  
    25.   
    26.     delete an1;  
    27.     an1 = NULL;  
    28. }  

    编译时,报如下错误信息:

    --------------------Configuration: CPlusPlusPrimer - Win32 Debug-------------------- Compiling... CPlusPlusPrimer.cpp E:StudyexampleCPlusPlusPrimerCPlusPlusPrimer.cpp(94) : error C2440: '=' : cannot convert from 'class animal *' to 'class fish *'         Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast Error executing cl.exe.
    CPlusPlusPrimer.exe - 1 error(s), 0 warning(s)
    根据以上错题提示信息,对代码做如下修改:

    1. void ExamAnimal()  
    2. {  
    3.     // 将子类指针直接赋给基类指针,不需要强制转换,C++编译器自动进行类型转换  
    4.     // 因为fish对象也是一个animal对象  
    5.     animal* pAn;  
    6.     fish* pfh = new fish;  
    7.     pAn = pfh;  
    8.       
    9.     delete pfh;  
    10.     pfh = NULL;  
    11.       
    12.     // 将基类指针直接赋给子类指针,需要强制转换,C++编译器不会自动进行类型转换  
    13.     // 因为animal对象不是一个fish对象  
    14.     fish* fh1;  
    15.     animal* an1 = new animal;  
    16.     // 修改处:  
    17.     // 进行强制类型转化  
    18.     fh1 = (fish*)an1;  
    19.   
    20.     delete an1;  
    21.     an1 = NULL;  
    22. }  

    再次编译,通过。
    二.子类指针赋给基类指针时内存分析 (1)int变量赋给char变量

     

    整型int转换为char类型时,只有一个字节的内容能够放进char类型,剩下的三个字节内容放不下,被截掉,丢失精度。 两个变量或者对象进行转换时,一定要看两者的内存模型是否互相匹配。
    (2)子类fish指针赋给基类animal指针 下面看看子类fish指针赋给基类animal指针时,内存的变化: 当我们构造fish类的对象时,首先要调用animal类的构造函数去构造animal类的构造函数,然后才调用fish类的构造函数完成自身部分的构造,从而拼接出一个完整的fish对象。当我们将fish类对象转换为animal类对象时,该对象就被认为是原对象整个内存模型的上半部分,也就是图中animal对象的内存部分。当我们利用类型转换后的对象指针去调用它的方法时,自然是调用它所在的内存中的方法。 在这里,animal类对象类似于char类型的对象,fish类对象类似于int类型的对象,将fish类对象赋给animal类对象时,会截取fish类对象自身的部分,剩下fish类对象中的animal部分。
    (2)基类animal指针赋给子类fish指针
    基类animal对象包含的信息少,类fish对象包含的信息多,将信息少的对象直接转换为信息多的对象时(没有强制类型转换),显然是无法构造出多出的信息。在编译时,也会发生如下错误:error C2440: '=' : cannot convert from 'class animal *' to 'class fish *'。 这时,需要做强制类型转换:

    1. // 将基类指针直接赋给子类指针,需要强制转换,C++编译器不会自动进行类型转换  
    2. // 因为animal对象不是一个fish对象  
    3. fish* fh1;  
    4. animal* an1 = new animal;  
    5. // 进行强制类型转化  
    6. fh1 = (fish*)an1;  
  • 相关阅读:
    JS开发框架DevExtreme v20.1.7上线
    Web开发:看如何定义Kendo UI Grid Width
    如何创建自定义DevExpress报表控件,看完你就懂了
    高性能HTML5/JavaScript开发框架DevExtreme全新发布v20.1.7|附下载
    WPF界面开发:如何将不同集合中的项目显示为同一父节点子项
    界面开发包DevExpress v20.1.7上线!即刻体验
    WPF界面开发2020:Scheduler等控件功能升级
    Winform界面开发看过来!一招教你使用属性网格自定义编辑器
    将从数据库查询出来的带有父子结构的list转换成treeList结构
    将JDBC ResultSet结果集转成List
  • 原文地址:https://www.cnblogs.com/cy568searchx/p/3508423.html
Copyright © 2020-2023  润新知