基类指针和子类指针相互赋值
首先,给出基类animal和子类fish
- //==============================================================
- // 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
//==============================================================
// 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
- #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;
- }
#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++编译器将不自动进行类型转换。因为基类对象不是一个子类对象。子类对象的自增部分是基类不具有的。
执行以下代码,看看会报什么错误:
- 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;
- }
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)
根据以上错题提示信息,对代码做如下修改:
- 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;
- }
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 *'。
这时,需要做强制类型转换:
- // 将基类指针直接赋给子类指针,需要强制转换,C++编译器不会自动进行类型转换
- // 因为animal对象不是一个fish对象
- fish* fh1;
- animal* an1 = new animal;
- // 进行强制类型转化
- fh1 = (fish*)an1;
基类指针和子类指针相互赋值相关推荐
- 基类Object的子类有哪些以及字符串和数组的方法
基类object的子类有: Function Ayyay Number Boolean String Date Math RegExp 都是类,本质都是函数 ...
- 写出一个类People,并由该类做基类派生出子类Employee和Teacher
写出一个类People,并由该类做基类派生出子类Employee和Teacher.其中People 类具有name.age两个保护成员变量,分别为String类型.整型,且具有公有的getAge成员函 ...
- 将派生类指针赋值给基类的指针
除了可以将派生类对象赋值给基类对象(对象变量之间的赋值),还可以将派生类指针赋值给基类指针(对象指针之间的赋值).我们先来看一个多继承的例子,继承关系为: #include <iostream& ...
- 谈谈基类与子类的this指针(C++)
引入 定义一个类的对象,首先系统已经给这个对象分配了空间,然后会调用构造函数(说明:假设存在构造函数).一个类有多个对象,当程序中调用对象的某个函数时,有可能要访问到这个对象的成员变量.而对于同一个类 ...
- c++ 虚函数多态、纯虚函数、虚函数表指针、虚基类表指针详解
文章目录 静态多态.动态多态 虚函数 哪些函数类型不可以被定义成虚函数? 虚函数的访问方式 析构函数中的虚函数 虚函数表指针 vptr 多继承下的虚函数表 虚基类表指针 bptr 纯虚函数 抽象类 虚 ...
- 向上转型(子类指针赋值给父类指针)
类其实也是一种数据类型,也可以发生数据类型转换,不过这种转换只有在基类(父类)和派生类(子类)之间才有意义,并且只能将派生类赋值给基类,包括将派生类对象赋值给基类对象.将派生类指针赋值给基类指针.将派 ...
- C++学习 对象模型之虚基类,虚基类表,虚基类表指针
1.虚基类 什么是虚基类,虚基类的作用是什么? 首先虚基类是为了解决多继承产生的二义性问题,范例代码如下: #include "stdafx.h" #include <std ...
- C/C++中的指针变量可以相互赋值,使得它们指向同一块地址空间
两个指针变量可以相互赋值吗? int *p, *q; p=q; 这样写是什么意思?是p指向q吗? 答:1.两个指针变量之间可以相互赋值,p和q都是int类型的指针. p=q表示将q所指向的int类型变 ...
- 继承类 基类的赋值_Chapter10:继承与派生(四)
之前的文章把继承和派生的基本概念和内部原理都大致理清了.但是类可以视作是一种特殊的数据类型--它也具有转换的功能,称为转型,这一节展开讨论它,以及如何通过指针跨越权限访问不同成员的技巧. 1.类的转型 ...
最新文章
- 蓝色梦想,再次起航 | 水下目标检测算法比赛正式开赛!
- 【动态规划】最长公子序列 - dp
- citespace与mysql_科学网—如何用CiteSpace整理数据 - 陈超美的博文
- 【收藏】IntelliJ Idea中配置JavaFX Scene Builder
- android mysql 图片_android sqlite添加图片到数据库
- 闲鱼账号被封怎么办?解封看这里!
- C 语言漏洞最严重,PHP 最易受攻击,程序员该怎么写代码?
- java里equals_Java中equals和==的区别
- Wacom发布Cintiq Companion 2
- 台式计算机液晶显示屏尺寸,台式电脑显示屏共有多少种尺寸?
- Mac Duet使用教程
- linux开发板挂载nfs服务
- 中国银联在线支付接口开发——前台支付
- x86服务器能装64位系统吗,x86处理器能装64位系统吗_64位系统装32位的可以么
- WARNING: --master-data is deprecated and will be removed in a future version
- vue表格el-table取到某一列求和的值
- 第三章 隐藏通信隧道技术
- 自动复制吱口令html,使用clipboard.js实现复制吱口令功能的示例代码
- 四旋翼飞行器轨迹跟踪仿真MATLAB simulink/simscape
- 方便你我他,百科全书:)
热门文章
- html5音频文件生成波形图代码,HTML5/D3.js 可视音频波形柱状图
- 执行sqoop 用shell_Mysql和Hive之间通过Sqoop进行数据同步
- 旅游网站的主页代码_山西太原网站SEO优化推广联系电话
- 计算机一级应用基础选择题,计算机应用选择题基础复习题 一级计算机考试必备...
- 前端服务器获取js文件偶尔慢_我所认识的前端性能优化
- 致初级开发者的一封信:坚持写代码!
- 自己动手写CPU(2)流水线数据相关问题
- 信用评分python_信用评分卡(python)
- basic中next转为c语言,[转载]混乱c语言代码写的basic解释器
- linux是数据库软件么,什么是适用于Linux的良好数据库ERD工具?