C++继承详细介绍
作者:是星星鸭 发布时间:2022-08-18 10:05:42
前言
可能会涉及到汇编的知识,不过这没有关系,肯定能看懂,看不懂留言,我再做解释。
使用到的工具是vs2010。
本节只讲继承的特点,公有私有多态等内容暂且不讲,以后会细说。
一、什么是继承
继承就是数据的复制
概念模糊、直接上代码:
#include <stdio.h>
#include <Windows.h>
struct Master // 父类(基类)
{
int a;
int b;
};
struct Slave:Master // 子类(派生类)
{
int c;
int d;
};
int main()
{
Slave slave;
slave.a = 1;
slave.b = 2;
slave.c = 3;
slave.d = 4;
int x = sizeof(slave);
system("pause"); // 此处下断点查看x的大小(子类的大小)
return 0;
}
运行,查看x的值:
16,这足以说明slave是拷贝了一份a和b给slave子类的。
查看汇编:
可以看出继承就是数据的复制
二、派生类和基类的成员重复问题
1、派生类和基类的成员可以重复吗?
2、重复的话是使用的哪一个类的成员呢?
解答如下:
1、派生类和基类的成员可以重复吗?
可以。
证明:
#include <stdio.h>
#include <Windows.h>
struct Master
{
int a;
int b;
};
struct Slave:Master
{
int a;
int d;
};
int main()
{
Slave slave;
printf("%d \n",sizeof(slave));
system("pause");
return 0;
}
运行:
不仅可以,而且slave类的大小依旧是16字节;
这说明了子类的a和父类的a是分开的,父类的a依旧被拷贝到了子类,尽管子类已经有成员a;
2、重复的话是使用的哪一个类的成员呢?
这样就不要使用变量来测试了,因为变量无法输出内容,很难分辨出是父类还是子类的,所以我们使用函数。
如下:
#include <stdio.h>
#include <Windows.h>
struct Master
{
void test()
{
printf("这是父类的测试。\n");
}
};
struct Slave:Master
{
void test()
{
printf("这是子类的测试。\n");
}
};
int main()
{
Slave slave;
slave.test();
system("pause");
return 0;
}
定义一父一子,类中都定义了test函数,那么子类的对象会调用谁的呢?
运行如下:
子类调用了子类的。
父类的对象会调用谁的呢?
测试如下:
运行:
父类调用父类。
可以看到,对象的默认调用都是本类自己定义的函数。
父类调用子类方法
父类可以调用子类方法吗?如何调用?子类又如何调用父类呢?
父类可以调用子类方法,步过需要一些手段;子类可以直接调用父类
先看一张图:
从这张图我们可以得知,子类包含了父类中允许继承的所有内容;但父类不包含任何子类的东西。
所以,子类可以直接调用父类是应该的,如下:
#include <stdio.h>
#include <Windows.h>
struct Master
{
void test()
{
printf("这是父类的测试。\n");
}
};
struct Slave:Master
{
void test()
{
printf("这是子类的测试。\n");
}
};
int main()
{
Slave slave;
slave.test();
slave.Master::test(); // 声明调用父类的内容即可
system("pause");
return 0;
}
运行如下:
可以看到,子类正常的调用了父类的方法;
如果父类直接调用子类的呢?
如下:
直接调用的话是不被允许的。
不过可以通过其他方法进行调用;
父类调用子类
我们知道,纯虚函数是必须要子类进行实现的,如果父类定义了纯虚函数,子类不进行实现,就会报错;我们可以通过这一点,让父类定义纯虚函数,子类来实现这个纯虚函数;然后父类定义指针(纯虚类就是接口类,无法定义对象,可以定义指针)来指向子类,调用子类的函数。
如下:
#include <stdio.h>
#include <Windows.h>
struct Master
{
virtual void test() = 0; // 父类定义纯虚函数
};
struct Slave:Master
{
void test() // 子类实现纯虚函数
{
printf("这是子类的测试。\n");
}
};
int main()
{
Slave slave;
slave.test(); // 子类正常调用
// Master master; // 不可以定义对象,会出错。
Master *master = &slave; // 可以定义指针指向子类
master->test();
system("pause");
return 0;
}
运行:
成功调用。
当然还有其他方法可以让父类调用子类,不过本文章只讲继承,不深入其他内容;大家感兴趣的话可以自己百度看看。
三、继承不仅仅局限于父类
怎么理解这个标题呢?就是说,不单单是父类可以有派生类,子类也可以有派生类。
如果子类有派生类,那么子类的派生类仅仅有父类的成员,还是既有父类的成员也有父类的父类成员?
观点:子类的派生类,即会拥有父类的公有成员也会拥有父类的父类的公有成员。
文字模糊,看图:
通过这张图我们可以知道:Son调用Slave的函数或者Master的函数可以直接调用;
Son包含Master和Slave所有公有成员、Slave只包含Master的公有成员、Master只包含自己的成员。
论证如下:
直接测试类所占用字节数就行了,如下:
#include <stdio.h>
#include <Windows.h>
struct Master
{
int a;
int b;
};
struct Slave:Master
{
int c;
int d;
};
struct Son:Slave
{
int e;
int f;
};
int main()
{
int MasterSize = sizeof(struct Master);
int SlaveSize = sizeof(struct Slave);
int SonSize = sizeof(struct Son);
printf("Master成员个数:\t%d\nSlave成员个数:\t\t%d\nSon成员个数:\t\t%d\n",MasterSize/4,SlaveSize/4,SonSize/4);
system("pause");
return 0;
}
Slave继承Master,Son继承Slave
三个类的成员都是int类型,所以通过类的字节数/4就可以知道这个类有几个成员
运行如下:
论证成功。
四、多重继承
就是说子类不单单可以继承一个父类,可以继承多个。
如下:
#include <stdio.h>
#include <Windows.h>
struct Master // 第一个父类
{
int a;
int b;
};
struct Slave // 第二个父类
{
int c;
int d;
};
struct Son:Slave,Master // 两个父类
{
int e;
int f;
};
int main()
{
int MasterSize = sizeof(struct Master);
int SlaveSize = sizeof(struct Slave);
int SonSize = sizeof(struct Son);
printf("Master成员个数:\t%d\nSlave成员个数:\t\t%d\nSon成员个数:\t\t%d\n",MasterSize/4,SlaveSize/4,SonSize/4);
system("pause");
return 0;
}
运行如下:
所以,如图:
这就是多重继承,但是多重继承增加了程序的复杂度,不建议使用 。
来源:https://blog.csdn.net/qq_52572621/article/details/127234843


猜你喜欢
- 本文实例讲述了Spring实战之Bean定义中的SpEL表达式语言支持操作。分享给大家供大家参考,具体如下:一 配置<?xml ver
- 直接上代码新建DecimalInputTextWatcher类继承TextWatcher (代码可直接复制使用) import androi
- 1. 需求描述有这样一个需求,用ViewPager实现图片滑动,其下方有一个tab,每一个tab的标签对应一组图片,在ViewPager中的
- 深色主题工具类package com.example.kotlindemo.utilsimport android.content.Cont
- 1、SpringMVC中默认集成SpringMVC已经默认集成了JackSon,如下所示: @RequestMapping(&q
- Java 线程同步根本上是要符合一个逻辑:加锁------>修改------>释放锁1、同步代码块示例如下:public cla
- 前言最近有一项需求,要定时判断任务执行条件是否满足并触发 Spark 任务,平时编写 Spark 任务时都是封装为一个 Jar 包,然后采用
- 互连网早期的时候,主机间的互连使用的是NCP协议。这种协议本身有很多缺陷,如:不能互连不同的主机,不能互连不同的操作系统,没有纠错功能。为了
- 相信对于手机的时间日期设置大家一定都不陌生吧,今天举一个关于时间日期设置的示例,其中有些许不完善之处,例如如何使设置的时间日期和手机系统同步
- using (TransactionScope tr = new TransactionScope()) {  
- 学习大佬们开发安全小工具,打包jar解决错误: 找不到或无法加载主类 main1 Maven方式遇到报错”找不到或无法加载主类 main“解
- 以下摘自胖哥分享的 2022开工福利教程。在学习Spring Security的时候你有没有下面这两个疑问:Spring Security的
- Common.cs: using System; using System.Collections.Generic; using Syste
- 1,刚刚在别人开源的项目中看到了一个挺不错的用户体验,效果图如下:2,那下面我们就来实现一下,首先看一下布局,由于一般只是我们包含头像的那部
- Java 7的这个新特性改变了警告的对象。构建这些类型毕竟有破坏类型安全的风险,这总得有人知道。但 API 的用户对此是无能为力的,不管do
- 问题描述使用@Autowired处理多个同种类型的bean,出现@Value和@Bean的执行顺序问题。首先使用扫描包+注解的方式注册Use
- 本文实例讲述了Android开发之OpenGL绘制2D图形的方法。分享给大家供大家参考,具体如下:Android为OpenGL ES支持提供
- 在之前的博客使用SpringMVC创建Web工程并使用SpringSecurity进行权限控制的详细配置方法 中,我们描述了如何配置一个基于
- 准备过程:在电脑桌面 右键点击 “此电脑”的“属性”选项选择“高级系统设置”选项点击下面的“环境变量”选项配置过程:点击“系统变量”下面的”
- 在c#中"??"为空合并运算符,用于定义可空类型和引用类型的默认值。(1)如果此运算符的左操作数不为 null,则此运算