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

[cpp] view plaincopy print?
  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

//==============================================================
//           animal.h
//
// begin   : 2012-06-30
// author  : zwq
// describe: 非虚函数情况下,将子类指针赋给积累指针,验证最终调用
//           基类函数还是子类函数。
//==============================================================
#ifndef ANIMAL_H
#define ANIMAL_H//===============================================================
//
//                animal
//               动物基类
//
//===============================================================
class animal
{
public:void breathe();      // 非虚函数
};//===============================================================
//
//                     animal
//               鱼类,集成于动物基类
//
//===============================================================
class fish : public animal
{
public:void breathe();      // 非虚函数
};#endif
[cpp] view plaincopy print?
  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. }

#include "StdAfx.h"
#include <iostream>
#include "Animal.h"using namespace std;//===============================================================
//
//                animal
//               动物基类
//
//===============================================================void animal::breathe()
{cout << "animal breathe" << endl;
}//===============================================================
//
//                     animal
//               鱼类,集成于动物基类
//
//===============================================================void fish::breathe()
{cout << "fish bubble" << endl;
}

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

(2)将基类指针赋值给子类指针时,需要进行强制类型转换,C++编译器将不自动进行类型转换。因为基类对象不是一个子类对象。子类对象的自增部分是基类不具有的。

执行以下代码,看看会报什么错误:

[cpp] view plaincopy print?
  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. }

int main(int argc, char* argv[])
{ExamAnimal();return 0;
}void ExamAnimal()
{// 将子类指针直接赋给基类指针,不需要强制转换,C++编译器自动进行类型转换// 因为fish对象也是一个animal对象animal* pAn;fish* pfh = new fish;pAn = pfh;delete pfh;pfh = NULL;// 将基类指针直接赋给子类指针,需要强制转换,C++编译器不会自动进行类型转换// 因为animal对象不是一个fish对象fish* fh1;animal* an1 = new animal;// 没有进行强制类型转化fh1 = an1;delete an1;an1 = NULL;
}

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

--------------------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)

根据以上错题提示信息,对代码做如下修改:

[cpp] view plaincopy print?
  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. }

void ExamAnimal()
{// 将子类指针直接赋给基类指针,不需要强制转换,C++编译器自动进行类型转换// 因为fish对象也是一个animal对象animal* pAn;fish* pfh = new fish;pAn = pfh;delete pfh;pfh = NULL;// 将基类指针直接赋给子类指针,需要强制转换,C++编译器不会自动进行类型转换// 因为animal对象不是一个fish对象fish* fh1;animal* an1 = new animal;// 修改处:// 进行强制类型转化fh1 = (fish*)an1;delete an1;an1 = NULL;
}

再次编译,通过。

二.子类指针赋给基类指针时内存分析
(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 *'。
这时,需要做强制类型转换:

[cpp] view plaincopy print?
  1. // 将基类指针直接赋给子类指针,需要强制转换,C++编译器不会自动进行类型转换
  2. // 因为animal对象不是一个fish对象
  3. fish* fh1;
  4. animal* an1 = new animal;
  5. // 进行强制类型转化
  6. fh1 = (fish*)an1;

基类指针和子类指针相互赋值相关推荐

  1. 基类Object的子类有哪些以及字符串和数组的方法

    基类object的子类有: Function     Ayyay   Number   Boolean    String     Date     Math    RegExp 都是类,本质都是函数 ...

  2. 写出一个类People,并由该类做基类派生出子类Employee和Teacher

    写出一个类People,并由该类做基类派生出子类Employee和Teacher.其中People 类具有name.age两个保护成员变量,分别为String类型.整型,且具有公有的getAge成员函 ...

  3. 将派生类指针赋值给基类的指针

    除了可以将派生类对象赋值给基类对象(对象变量之间的赋值),还可以将派生类指针赋值给基类指针(对象指针之间的赋值).我们先来看一个多继承的例子,继承关系为: #include <iostream& ...

  4. 谈谈基类与子类的this指针(C++)

    引入 定义一个类的对象,首先系统已经给这个对象分配了空间,然后会调用构造函数(说明:假设存在构造函数).一个类有多个对象,当程序中调用对象的某个函数时,有可能要访问到这个对象的成员变量.而对于同一个类 ...

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

    文章目录 静态多态.动态多态 虚函数 哪些函数类型不可以被定义成虚函数? 虚函数的访问方式 析构函数中的虚函数 虚函数表指针 vptr 多继承下的虚函数表 虚基类表指针 bptr 纯虚函数 抽象类 虚 ...

  6. 向上转型(子类指针赋值给父类指针)

    类其实也是一种数据类型,也可以发生数据类型转换,不过这种转换只有在基类(父类)和派生类(子类)之间才有意义,并且只能将派生类赋值给基类,包括将派生类对象赋值给基类对象.将派生类指针赋值给基类指针.将派 ...

  7. C++学习 对象模型之虚基类,虚基类表,虚基类表指针

    1.虚基类 什么是虚基类,虚基类的作用是什么? 首先虚基类是为了解决多继承产生的二义性问题,范例代码如下: #include "stdafx.h" #include <std ...

  8. C/C++中的指针变量可以相互赋值,使得它们指向同一块地址空间

    两个指针变量可以相互赋值吗? int *p, *q; p=q; 这样写是什么意思?是p指向q吗? 答:1.两个指针变量之间可以相互赋值,p和q都是int类型的指针. p=q表示将q所指向的int类型变 ...

  9. 继承类 基类的赋值_Chapter10:继承与派生(四)

    之前的文章把继承和派生的基本概念和内部原理都大致理清了.但是类可以视作是一种特殊的数据类型--它也具有转换的功能,称为转型,这一节展开讨论它,以及如何通过指针跨越权限访问不同成员的技巧. 1.类的转型 ...

最新文章

  1. 蓝色梦想,再次起航 | 水下目标检测算法比赛正式开赛!
  2. 【动态规划】最长公子序列 - dp
  3. citespace与mysql_科学网—如何用CiteSpace整理数据 - 陈超美的博文
  4. 【收藏】IntelliJ Idea中配置JavaFX Scene Builder
  5. android mysql 图片_android sqlite添加图片到数据库
  6. 闲鱼账号被封怎么办?解封看这里!
  7. C 语言漏洞最严重,PHP 最易受攻击,程序员该怎么写代码?
  8. java里equals_Java中equals和==的区别
  9. Wacom发布Cintiq Companion 2
  10. 台式计算机液晶显示屏尺寸,台式电脑显示屏共有多少种尺寸?
  11. Mac Duet使用教程
  12. linux开发板挂载nfs服务
  13. 中国银联在线支付接口开发——前台支付
  14. x86服务器能装64位系统吗,x86处理器能装64位系统吗_64位系统装32位的可以么
  15. WARNING: --master-data is deprecated and will be removed in a future version
  16. vue表格el-table取到某一列求和的值
  17. 第三章 隐藏通信隧道技术
  18. 自动复制吱口令html,使用clipboard.js实现复制吱口令功能的示例代码
  19. 四旋翼飞行器轨迹跟踪仿真MATLAB simulink/simscape
  20. 方便你我他,百科全书:)

热门文章

  1. html5音频文件生成波形图代码,HTML5/D3.js 可视音频波形柱状图
  2. 执行sqoop 用shell_Mysql和Hive之间通过Sqoop进行数据同步
  3. 旅游网站的主页代码_山西太原网站SEO优化推广联系电话
  4. 计算机一级应用基础选择题,计算机应用选择题基础复习题 一级计算机考试必备...
  5. 前端服务器获取js文件偶尔慢_我所认识的前端性能优化
  6. 致初级开发者的一封信:坚持写代码!
  7. 自己动手写CPU(2)流水线数据相关问题
  8. 信用评分python_信用评分卡(python)
  9. basic中next转为c语言,[转载]混乱c语言代码写的basic解释器
  10. linux是数据库软件么,什么是适用于Linux的良好数据库ERD工具?