C++ 基类指针和子类指针相互赋值
首先,给出基类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
- #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;
- }
编译时,报如下错误信息:
--------------------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部分。
(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;
C++ 基类指针和子类指针相互赋值的更多相关文章
- C++ 基类指针,子类指针,多态
基类指针和子类指针之间相互赋值(1)将子类指针赋值给基类指针时,不需要进行强制类型转换,C++编译器将自动进行类型转换.因为子类对象也是一个基类对象. (2)将基类指针赋值给子类指针时,需要进行强制类 ...
- 基类用的this指针
结论:基类构造函数中的this指针指向的是派生类的对象 测试代码: #include <iostream> using namespace std; class father; fathe ...
- .NET Core中基类可以反射子类的成员
我们定义一个类DemoA,再定义一个类DemoB继承DemoA.当构造一个DemoB类对象后,我们可以通过其调用基类DemoA中的方法来反射子类DemoB的成员. 新建一个.NET Core控制台项目 ...
- DRF基类APIView的子类GenericAPIView
DRF的基类是APIView类,GenericAPIView类是APIView类的子类. GenericAPIView类有什么存在的意义呢? 其实, 他主要提供了两个用处: 1.提供关于数据库查询的属 ...
- C++基础知识 基类指针、虚函数、多态性、纯虚函数、虚析构
一.基类指针.派生类指针 父类指针可以new一个子类对象 二.虚函数 有没有一个解决方法,使我们只定义一个对象指针,就可以调用父类,以及各个子类的同名函数? 有解决方案,这个对象指针必须是一个父类类型 ...
- 当this指针成为指向之类的基类指针时,也能形成多态
this指针: 1)对象中没有函数,只有成员变量 2)对象调用函数,通过this指针告诉函数是哪个对象自己谁. #include<iostream> using namespace std ...
- c++ 虚函数多态、纯虚函数、虚函数表指针、虚基类表指针详解
静态多态.动态多态 静态多态:程序在编译阶段就可以确定调用哪个函数.这种情况叫做静态多态.比如重载,编译器根据传递给函数的参数和函数名决定具体要使用哪一个函数.动态多态:在运行期间才可以确定最终调用的 ...
- Java: 基类、子类、构造函数、程序块的初始化顺序
初始化顺序 基类static block 子类static block 基类non-static block 子类non-static block 基类constructor 子类constructo ...
- C++ | 继承(基类,父类,超类),(派生类,子类)
转载:https://blog.csdn.net/Sherlock_Homles/article/details/82927515 文章参考:https://blog.csdn.net/war1111 ...
随机推荐
- 【提醒】使用 iptables 时,特别注意 规则的顺序
在 centos 上安装 redis 服务器,很快就搞定了,服务器上使用 redis-cl 测试都没有问题了. 但到宿主机上测试,怎么测试都不通过,关键是:关闭了 centos 的 Iptables ...
- qt 中文乱码 处理QByteArray类型里含中文的数据
qt解析tcp通信传来的xml时,中文有乱码 解决方法: 头文件加入 #include <QTextCodec> QByteArray tmpQBA = m_pSocket->rea ...
- linux有用技巧:使用ntfs-3g挂载ntfs设备
1.几种文件系统的比較 (1)在linux系统中支持一下文件系统: Ext2 第二扩展文件系统(简称 ext2 或者 ext2) 非常多年前就已经成为 GN ...
- VB开发ActiveX控件的一些记录
注意,下面很多语句的用法,不能放在Private Sub UserControl_Initialize()里使用,要放在Private Sub UserControl_InitProperties() ...
- 10723 Cyborg Genes (LCS + 记忆化搜索)
Problem F Cyborg Genes Time Limit 1 Second September 11, 2132. This is the day that marks the beginn ...
- 如何对exec sp_who2的结果进行选择和排序?
从网上找到了下面的两个脚本, 笔者试用过, 很好. 故记在这里. 方法一, 用临时表 CREATE TABLE #sp_who2 ( SPID INT, Status VARCHAR(255), ...
- javascript刷新父页面方法总结
用iframe.弹出子页面刷新父页面iframe <script language=JavaScript> parent.location.reload(); </script> ...
- React 同构思想
作者:yangchunwen React比较吸引我的地方在于其客户端-服务端同构特性,服务端-客户端可复用组件,本文来简单介绍下这一架构思想. 出于篇幅原因,本文不会介绍React基础,所以,如果你还 ...
- 用php当作cat使用
今天,本来是想敲 node test.js 执行一下,test.js文件,结果 惯性的敲成了 php test.js, 原文输出了 test.js的内容. 突然觉得,这东西 感觉好像是 cat 命 ...
- 解决Ubuntu Ping网关Destination Host Unreachable错误
ifconfig 检查了配置,没问题,是ok的, 检查了防火墙,是关闭的,邪乎了,是什么问题呢 各种尝试,最后,将 ip 搞成自动获取就 可以ping通了,但为啥手动设置就不行呢? 最后看了这个朋友的 ...