浅谈C++ 基类指针和子类指针的相互赋值

 更新时间:2020年4月25日 17:33  点击:1960

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

//============================================================== 
//      animal.h 
// 
// author : zwq 
// describe: 非虚函数情况下,将子类指针赋给积累指针,验证最终调用 
//      基类函数还是子类函数。 
//============================================================== 
#ifndef ANIMAL_H 
#define ANIMAL_H 
 
//=============================================================== 
// 
//        animal 
//        动物基类 
// 
//=============================================================== 
class animal 
{ 
public: 
  void breathe();   // 非虚函数 
}; 
 
//=============================================================== 
// 
//           animal 
//        鱼类,集成于动物基类 
// 
//=============================================================== 
class fish : public animal 
{ 
public: 
  void breathe();   // 非虚函数 
}; 
 
#endif 

#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++编译器将不自动进行类型转换。因为基类对象不是一个子类对象。子类对象的自增部分是基类不具有的。

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

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

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

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

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部分。

(3)基类animal指针赋给子类fish指针

基类animal对象包含的信息少,类fish对象包含的信息多,将信息少的对象直接转换为信息多的对象时(没有强制类型转换),显然是无法构造出多出的信息。在编译时,也会发生如下错误:error C2440: '=' : cannot convert from 'class animal *' to 'class fish *'。 这时,需要做强制类型转换:

// 将基类指针直接赋给子类指针,需要强制转换,C++编译器不会自动进行类型转换 
// 因为animal对象不是一个fish对象 
fish* fh1; 
animal* an1 = new animal; 
// 进行强制类型转化 
fh1 = (fish*)an1; 

以上就是小编为大家带来的浅谈C++ 基类指针和子类指针的相互赋值全部内容了,希望大家多多支持猪先飞~

[!--infotagslink--]

相关文章

  • php数组操作 键名比较 差集 交集赋值

    本文章提供在量的数据中级操作实例有如对键名比较计算数组的差集 计算差集 给指定数组中插入一个元素 反转数组 交集赋值新的数组实例。 //定义回调函数 funct...2016-11-25
  • c# 判断是否为空然后赋值的4种实现方法

    下面小编就为大家分享一篇c# 判断是否为空然后赋值的4种实现方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-06-25
  • vue 数据(data)赋值问题的解决方案

    这篇文章主要介绍了vue 数据(data)赋值问题的解决方案,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-29
  • java中String类型变量的赋值问题介绍

    下面小编就为大家带来一篇java中String类型变量的赋值问题介绍。小编觉得挺不错的。现在分享给大家,给大家一个参考。...2016-03-28
  • python 实现循环定义、赋值多个变量的操作

    这篇文章主要介绍了python 实现循环定义、赋值多个变量的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-09
  • react使用antd表单赋值,用于修改弹框的操作

    这篇文章主要介绍了react使用antd表单赋值,用于修改弹框的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-10-29
  • java中的空指针异常情况以及解决方案

    这篇文章主要介绍了java中的空指针异常情况以及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-10-02
  • postgresql 补齐空值、自定义查询字段并赋值操作

    这篇文章主要介绍了postgresql 补齐空值、自定义查询字段并赋值操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-16
  • 基于C#调用c++Dll结构体数组指针的问题详解

    下面小编就为大家分享一篇基于C#调用c++Dll结构体数组指针的问题详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-06-25
  • AngularJS中如何使用$parse或$eval在运行时对Scope变量赋值

    这篇文章主要介绍了AngularJS中如何使用$parse或$eval在运行时对Scope变量赋值的相关资料,本文介绍的非常详细,具有参考借鉴价值,需要的朋友可以参考下...2016-01-26
  • JS实现DIV容器赋值的方法

    这篇文章主要介绍了JS实现DIV容器赋值的方法,可结合ajax使用,涉及JavaScript针对页面元素的动态操作技巧,需要的朋友可以参考下...2015-12-16
  • python for循环赋值问题

    这篇文章主要介绍了python for循环赋值问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-06-03
  • C# 通过反射获取类型的字段值及给字段赋值的操作

    这篇文章主要介绍了C# 通过反射获取类型的字段值及给字段赋值的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-19
  • chrome监听cookie变化与赋值问题

    这篇文章主要介绍了chrome监听cookie变化与赋值问题,cookie监听与赋值操作需要manifest文件里声明权限问题,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-10-22
  • C++交换指针实例

    这篇文章主要介绍了C++交换指针实例,针对C与C++交换指针的方法进行了较为详细的对比分析,非常具有实用价值,需要的朋友可以参考下...2020-04-25
  • Javascript中的解构赋值语法详解

    这篇文章主要给大家介绍了关于Javascript中解构赋值语法的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-04-02
  • 浅谈C#指针问题

    在C#中,有时候希望通过指针来操作内存,这样可以提高效率。我们可以用unsafe关键字修饰含有指针操作的程序段...2020-06-25
  • SQL SERVER中SELECT和SET赋值相同点与不同点(推荐)

    SELECT和SET在SQL SERVER中都可以用来对变量进行赋值,但其用法和效果在一些细节上有些不同。今天小编给大家分享SQL SERVER中SELECT和SET赋值相同点与不同点,感兴趣的朋友一起看看吧...2020-07-11
  • 详解C++数组和数组名问题(指针、解引用)

    这篇文章主要介绍了详解C++数组和数组名问题(指针、解引用),指针的实质就是个变量,它跟普通变量没有任何本质区别,指针本身是一个对象,同时指针无需在定义的时候赋值,具体内容详情跟随小编一起看看吧...2021-09-18
  • C++ 函数指针详细总结

    这篇文章主要介绍了C++ 函数指针内容,下面文章围绕C++ 函数指针的相关资料展开详细内容,包括函数指针的进阶内容,需要的朋友可以参考一下,希望对大家有所帮助...2021-11-16