首先,给出基类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. //                animal
  14. //               动物基类
  15. //
  16. //===============================================================
  17. class animal
  18. {
  19. public:
  20. void breathe();     // 非虚函数
  21. };
  22. //===============================================================
  23. //
  24. //                     animal
  25. //               鱼类,集成于动物基类
  26. //
  27. //===============================================================
  28. class fish : public animal
  29. {
  30. public:
  31. void breathe();     // 非虚函数
  32. };
  33. #endif
  1. #include "StdAfx.h"
  2. #include <iostream>
  3. #include "Animal.h"
  4. using namespace std;
  5. //===============================================================
  6. //
  7. //                animal
  8. //               动物基类
  9. //
  10. //===============================================================
  11. void animal::breathe()
  12. {
  13. cout << "animal breathe" << endl;
  14. }
  15. //===============================================================
  16. //
  17. //                     animal
  18. //               鱼类,集成于动物基类
  19. //
  20. //===============================================================
  21. void fish::breathe()
  22. {
  23. cout << "fish bubble" << endl;
  24. }

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

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

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

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

--------------------Configuration: CPlusPlusPrimer - Win32 Debug-------------------- Compiling... CPlusPlusPrimer.cpp E:\Study\example\CPlusPlusPrimer\CPlusPlusPrimer.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. delete pfh;
  9. pfh = NULL;
  10. // 将基类指针直接赋给子类指针,需要强制转换,C++编译器不会自动进行类型转换
  11. // 因为animal对象不是一个fish对象
  12. fish* fh1;
  13. animal* an1 = new animal;
  14. // 修改处:
  15. // 进行强制类型转化
  16. fh1 = (fish*)an1;
  17. delete an1;
  18. an1 = NULL;
  19. }

再次编译,通过。
二.子类指针赋给基类指针时内存分析 (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;

C++ 基类指针和子类指针相互赋值的更多相关文章

  1. C++ 基类指针,子类指针,多态

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

  2. 基类用的this指针

    结论:基类构造函数中的this指针指向的是派生类的对象 测试代码: #include <iostream> using namespace std; class father; fathe ...

  3. .NET Core中基类可以反射子类的成员

    我们定义一个类DemoA,再定义一个类DemoB继承DemoA.当构造一个DemoB类对象后,我们可以通过其调用基类DemoA中的方法来反射子类DemoB的成员. 新建一个.NET Core控制台项目 ...

  4. DRF基类APIView的子类GenericAPIView

    DRF的基类是APIView类,GenericAPIView类是APIView类的子类. GenericAPIView类有什么存在的意义呢? 其实, 他主要提供了两个用处: 1.提供关于数据库查询的属 ...

  5. C++基础知识 基类指针、虚函数、多态性、纯虚函数、虚析构

    一.基类指针.派生类指针 父类指针可以new一个子类对象 二.虚函数 有没有一个解决方法,使我们只定义一个对象指针,就可以调用父类,以及各个子类的同名函数? 有解决方案,这个对象指针必须是一个父类类型 ...

  6. 当this指针成为指向之类的基类指针时,也能形成多态

    this指针: 1)对象中没有函数,只有成员变量 2)对象调用函数,通过this指针告诉函数是哪个对象自己谁. #include<iostream> using namespace std ...

  7. c++ 虚函数多态、纯虚函数、虚函数表指针、虚基类表指针详解

    静态多态.动态多态 静态多态:程序在编译阶段就可以确定调用哪个函数.这种情况叫做静态多态.比如重载,编译器根据传递给函数的参数和函数名决定具体要使用哪一个函数.动态多态:在运行期间才可以确定最终调用的 ...

  8. Java: 基类、子类、构造函数、程序块的初始化顺序

    初始化顺序 基类static block 子类static block 基类non-static block 子类non-static block 基类constructor 子类constructo ...

  9. C++ | 继承(基类,父类,超类),(派生类,子类)

    转载:https://blog.csdn.net/Sherlock_Homles/article/details/82927515 文章参考:https://blog.csdn.net/war1111 ...

随机推荐

  1. UIScrollView 几乎所有的属性和方法

    - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typica ...

  2. mysql重启,重启释放ibtmp1

    1.通过rpm包安装的MySQL service mysqld restart 2.从源码包安装的MySQL // linux关闭MySQL的命令$mysql_dir/bin/mysqladmin - ...

  3. 数学图形(2.13)Spherical trochoid曲线

    该曲线与上一节的herical cycloid球面外摆曲线 很相似,难道这是球面内摆曲线? #http://www.mathcurve.com/courbes3d/cycloidspheric/tro ...

  4. Hydra 无法爆破SSH 解决办法

    今天测试ssh爆破,发现使用hydra有些问题,windows版本没有协议支持其他的貌似都可以,kali本身也有hydra环境但是也会出现问题,所以就搜了一些资料贴在这里,当然这也是我测试过的,重新编 ...

  5. Ubuntu 12.04 LTS安装Windows字体

    内容参考自别人的博客:http://www.cnblogs.com/zhj5chengfeng/p/3251009.html 1. 为了方便,先将Windows字体拷贝到~/WinFonts下. 我是 ...

  6. go语言基础之运算符

    一.运算符分类 1.1 算术运算符 运算符 术语 示例 结果 + 加 10 + 5 15 - 减 10 - 5 5 * 乘 10 * 5 50 / 除 10 / 5 2 % 取模(取余) 10 % 3 ...

  7. Java里面类型转换总结

    1.String 转 int int i = Integer.valueOf(my_str).intValue(); int i = Integer.parseInt(str); 2.String 转 ...

  8. PHP的错误处理方式(开发和上线)

    对于PHP开发人员来说,一旦某个产品投入使用.应该马上将 display_errors选项关闭.以免由于这些错误所透露的路径.数据库连接.数据表等信息而遭到黑客攻击. 可是.不论什么一个产品在投入使用 ...

  9. php 上传视频的代码,

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  10. [Algorithm] Array production problem

    Given an array of integers, return a new array such that each element at index i of the new array is ...