当前位置: 首页 > news >正文

2,继承、内联函数、虚继承、友元、构造析构函数、初始化列表

继承

  • 2.1结构体成员权限
    • 2.1.1访问权限
    • 2.1.2类与结构体
  • 2.2类的成员函数
    • 2.2.1类内规则
    • 2.2.2类成员内联函数inline
  • 2.3类的继承
    • 2.3.1类的继承与成员函数
    • 2.3.2类的多继承
      • 2.3.2.1类的多继承:菱形问题提出
    • 2.3.3类的虚继承(关键字virtual)
  • 2.4友元
    • 2.4.1友元类
    • 2.4.2友元函数
  • 2.5构造函数和析构函数
  • 2.6初始化列表

2.1结构体成员权限

2.1.1访问权限

访问权限有三种:
public 公共权限(类内可以访问,类外可以访问)

protected 保护权限(类内可以访问,类外不可以访问)(子类可以访问父类中的保护内容)

private 私有权限(类内可以访问,类外不可以访问)(子类不可以访问父类中的私有内容)

注意:protected 和 private 的设计是为了继承

2.1.2类与结构体

类:
类在游戏开发中用的最多
如果没有在类中显式定义构造函数和析构函数并指定访问权限,则默认情况下它们的权限都是公有的(public)
结构体:
结构体一般用于储存变量或数据
结构体也有构造(初始化)和析构(释放内存等),不写编译器就会默认生成,在游戏中对对象的生命周期的操作

#include<iostream>
using namespace std;
struct Test01
{
public:int a;void test01() {}
protected:int b;void test02() {}
private:float c;void test03() {}
};
class Test02
{
public:int d;void test04() {}
protected:int e;void test05() {}
private:float f;void test06() {}
};
int main()
{Test01 A;A.a = 10;int num1 = A.a;A.test01();//A.c;//因为设置了保护权限,所以不可以访问//A.test03();//因为设置了私有权限,所以不可以访问Test02 B;B.d = 20;int num2 = B.d;B.test04();//B.e;//因为设置了保护权限,所以不可以访问//B.test06();//因为设置了私有权限,所以不可以访问system("pause");return 0;
}

2.2类的成员函数

2.2.1类内规则

类内可以写静态函数、成员函数
静态函数不可以调用成员函数,成员函数可以调用静态函数
静态函数内不可以包含类内的成员信息(如果想调用需要使成员信息也变为静态)
全局的调用方式::

#include<iostream>
using namespace std;
int Fun1()
{return 1;
}class Test01
{
public:Test01();~Test01();static int a;static int b;static int Fun1()//类内可以添加静态函数{return a+b; //无法直接调用int a;和int b;需要转换为static形式}int Fun2()//类内可以添加成员函数{Test01::Fun1();//成员函数可以调用静态函数return 3;}
};
int Test01::a = 0;
int Test01::b = 0;
Test01::Test01()
{int num1 = ::Fun1();//::调用全局范围中的cout << num1 << endl;
}
Test01::~Test01()
{}struct Test02
{
public:static void Fun1();
};void Test02::Fun1() {}
int main()
{Test01 A;//实例化Test01::Fun1();A.Fun1();A.Fun2();Test02::Fun1();system("pause");return 0;
}

2.2.2类成员内联函数inline

为什么inline的效率会高效,因为编译时编译器会把代码副本放在每个调用函数的地方

可以使用在类成员内,也可以使用在全局中,也可以使用在结构体内

将简短的、频繁调用的函数声明为内联函数可以获得较好的效果。但是,对于复杂的函数或者在循环中调用的函数,使用内联可能导致代码膨胀,反而会影响性能如for、switch、递归等。

ue4中的FORCEINLINE也代表着内敛的效果,使用FORCEINLINE使需要包含头文件“CoreMinimal.h”

#include<iostream>
using namespace std;
class Test01
{
public://想要获取私有成员,不想私有成员被赋值可以用inline//比下面注释中的代码高效很多inline int Geta()const{return a;}/*int Geta()const{return a;}*/
private:int a;
};inline int Getb()
{return 0;
}struct Test02
{
public:inline int Getc()const{return c;}
private:int c;
};int main()
{Test01 A;A.Geta();Getb();Test02 C;C.Getc();system("pause");return 0;
}

2.3类的继承

2.3.1类的继承与成员函数

父类也成为基类,子类也称为派生类
封装SDK(插件)时只需要封装基类,其他人使用时只需要继承即可使用其中的方法,或者去扩展
游戏开发时大部分用的都是公共继承

//public
//   public      public
//   protected   protected
//   private     private
//provected
//   public      protected
//   protected   protected
//   private     private
//private
//   public      private
//   protected   private
//   private     private

2.3.2类的多继承

使用场景:如下列代码,将每一个系统部分封装到各个模块中,需要使用时直接调用即可,非常方便
可以将对象转换成某个模块
不需要直接转换成类,可以直接调接口,三个指针指向不同的继承接口,所以可以直接通过指针
请添加图片描述

#include<iostream>
using namespace std;
class UObject
{};class AActor :public UObject//只管和对象有关的
{
public:void Start() {}void End() {}void Net() {}
};class IPhysics//只管物理
{
public:void Simulate() {}
};class IAttack//攻击接口
{
public:void AttackTarget(ACharacter* InTarget) {}
};class ACharacter :public AActor,public IPhysics,public IAttack
{};bool IsSimulate(IPhysics* p)//好处是不需要直接转换成类,可以直接调接口
{if (p){p->Simulate();}return true;
}
int main()
{ACharacter A;//多继承ACharacter B;A.Start();A.End();A.Simulate();A.AttackTarget(&B);//A为多继承的,继承了IPhysics、IAttack、AActorIPhysics* p = &A;
//因为A继承了IPhysics接口(通过ACharacter类的多继承),
//A对象可以被视为一个IPhysics对象
//将A对象的地址赋值给指针p,就可以通过指针p来访问A对象的IPhysics接口IAttack* p1 = &A;AActor* p2 = &A;IsSimulate(&A);system("pause");return 0;
}

2.3.2.1类的多继承:菱形问题提出

A的类型为ACharacter,同时继承了AActor和UHello,而AActor和UHello同时继承了UObject,用A调用UObject时会出现二义性,不知道调用的是AActor的UObject还是UHello的UObject
A.Destroy();调用的是UHello的还是AActor的?
这既是菱形问题,要避免
解决菱形问题需要用到虚函数,在下文会解决

#include<iostream>
using namespace std;
class UObject
{
public:void Destroy() {}
};class AActor :public UObject//只管和对象有关的
{
public:void Start() {}void End() {}void Net() {}
};class UHello :public UObject
{};class IPhysics//只管物理
{
public:void Simulate() {}
};class ACharacter;//因为class ACharacter在后面,所以先声明,也可以在IAttak内部使用前加class
class IAttack//攻击接口
{
public:void AttackTarget(class ACharacter* InTarget) {}
};class ACharacter :public AActor,public IPhysics,public IAttack,public UHello
{};bool IsSimulate(IPhysics* p)//好处是不需要直接转换成类,可以直接调接口
{if (p){p->Simulate();}return true;
}
int main()
{ACharacter A;IPhysics* p = &A;IAttack* p1 = &A;AActor* p2 = &A;IsSimulate(&A);//A.Destroy();//会报错,类型不明确//调用的是UHello的还是AActor的system("pause");return 0;
}

2.3.3类的虚继承(关键字virtual)

虚继承使class B和class C继承的public A变成一个共享的类,因此class D只用调用一次A
尽量避免虚继承问题

#include<iostream>
using namespace std;
class A
{
public:A(){printf("A\n");}void Hello(){printf("Hello\n");}
};
class B :virtual public A
{
public:B() :A() {}
};
class C :virtual public A
{
public:C() :A() {}
};
class D :public B, public C
{
public:D()//c保错,编译器不知道构造B还是C{}~D() {}
};
int main()
{D d;d;//没虚继承前输出结果为A输出了两次//A//Ad.Hello();//正常情况下会报错,在class B和C的继承public A前加上virtual变为虚继承//输出结果为//A//Hellosystem("pause");return 0;
}

2.4友元

2.4.1友元类

使用友元可以访问另一个类内的所有内容

#include<iostream>
using namespace std;
class FTestClass
{friend class FTest2;//友元
public:void Hello() {}
private:void Hello1() {}void Hello2() {}void Hello3() {}
protected:void Hello4() {}
};class FTest2
{
public:void Init(){Class.Hello();Class.Hello1();//因为是private权限,正常会报错,使用友元不会报错Class.Hello4();//因为是protected权限,正常会报错,使用友元不会报错}
private:FTestClass Class;
};int main()
{FTest2 Test2;Test2.Init();system("pause");return 0;
}

2.4.2友元函数

友元不能被继承
优点:提高了程序的运行效率
缺点:破坏了类的封装以及稳点性
友元关系本身不具备继承性

#include<iostream>
using namespace std;
class FTest1
{
public:friend void Printf_f(FTest1 &T){T.Hello();printf("%d\n", T.a);printf("%d\n", T.b);}void Printf_a(){printf("%d\n", a);printf("%d\n", b);printf("%d\n", c);}int c = 100;static void Printf_b(FTest1& T){T.Hello();printf("%d\n", T.a);printf("%d\n", T.b);}
private:void Hello(){a = 0;//其实是this->a=0;编译器省略了b = 10;}
private:int a;int b;
};int main()
{FTest1 A;Printf_f(A);A.Printf_a();FTest1::Printf_b(A);//静态函数system("pause");return 0;
}

2.5构造函数和析构函数

#include<iostream>
using namespace std;
class FTest1
{
public:};class FTestA
{
public:FTestA();FTestA(int ina, int inb, int inc);~FTestA();
public:int a;int b;int c;FTest1* T;
};FTestA::FTestA()
{a = 1;b = 2;c = 3;
}FTestA::FTestA(int ina, int inb, int inc)
{a = ina;b = inb;c = inc;T = new FTest1();//分配内存
}FTestA::~FTestA()
{if (T){delete T;T = nullptr;//将指针类型的变量 T 初始化为空指针}
}int main()
{FTestA A;//会走FTestA::FTestA()cout << A.a << " " << A.b << " " << A.c << endl;FTestA B(10,20,30);//会走FTestA(int ina, int inb, int inc);cout << B.a << " " << B.b << " " << B.c << endl;system("pause");return 0;
}

2.6初始化列表

初始化列表的语法是在构造函数的参数列表后使用冒号 “:”,接着是多个初始化器,每个初始化器由成员变量名和对应的初始值用逗号分隔。
有父类时父类排在最前面
一定要按照变量声明的顺序排列

初始化列表的优点:
初始化非静态常量成员变量:对于非静态常量成员变量,它们只能在初始化列表中进行赋值,不能在构造函数中赋值。
初始化引用成员变量:引用成员变量必须在构造函数中进行初始化,并且只能使用初始化列表进行初始化。
初始化基类成员变量:如果派生类包含一个基类,那么初始化列表可以用于调用基类的构造函数,并初始化基类成员变量。
性能优化:使用初始化列表可以避免先创建再赋值的过程,提高效率。

注意:
初始化列表只能在构造函数中使用
初始化顺序固定
初始化列表只能在编译时确定初始值,无法在运行时根据条件或变量的值来决定初始值。
初始化列表中的初始化操作无法直接处理异常或错误。

#include<iostream>
using namespace std;
class FTest1
{
public:};class FHello_F{};class FTestA:public FHello_F
{
public:FTestA();FTestA(int ina, int inb, int inc);~FTestA();
public:int a;int b;int c;FTest1* T;
};FTestA::FTestA()
{a = 1;b = 2;c = 3;
}FTestA::FTestA(int ina, int inb, int inc)
//初始化列表:FHello_F()//有父类时放在最前面,a(ina)//一定要按照变量声明的顺序排列,b(inb),c(inc)
{T = new FTest1();//分配内存
}FTestA::~FTestA()
{if (T){delete T;T = nullptr;}
}int main()
{FTestA A;//会走FTestA::FTestA()cout << A.a << " " << A.b << " " << A.c << endl;FTestA B(10,20,30);//会走FTestA(int ina, int inb, int inc);cout << B.a << " " << B.b << " " << B.c << endl;system("pause");return 0;
}

相关文章:

2,继承、内联函数、虚继承、友元、构造析构函数、初始化列表

继承 2.1结构体成员权限2.1.1访问权限2.1.2类与结构体 2.2类的成员函数2.2.1类内规则2.2.2类成员内联函数inline 2.3类的继承2.3.1类的继承与成员函数2.3.2类的多继承2.3.2.1类的多继承&#xff1a;菱形问题提出 2.3.3类的虚继承&#xff08;关键字virtual&#xff09; 2.4友元…...

Mkdocs中利用Js实现大小圈鼠标拖动样式

在docs/javascripts/extra.js下复制粘贴&#xff1a; var CURSOR;Math.lerp (a, b, n) > (1 - n) * a n * b;const getStyle (el, attr) > {try {return window.getComputedStyle? window.getComputedStyle(el)[attr]: el.currentStyle[attr];} catch (e) {}return …...

pytorch(6)——神经网络基本骨架nn.module的使用

1 神经网络框架 1.1 Module类的使用 NN (Neural network): 神经网络 Containers: 容器 Convolution Layers: 卷积层 Pooling layers: 池化层 Padding Layers: 填充层 Non-linear Activations (weighted sum, nonlinearity): 非线性激活 Non-linear Activations (other): 非线…...

论文精读之BERT

目录 1.摘要&#xff08;Abstract&#xff09; 2.引言&#xff08;Introduction&#xff09;&#xff1a; 3.结论&#xff08;Conlusion&#xff09;&#xff1a; 4.BERT模型算法: 5.总结 1.摘要&#xff08;Abstract&#xff09; 与别的文章的区别是什么:BERT是用来设计去…...

实战:Docker+Jenkins+Gitee构建CICD流水线

文章目录 前言Jenkins部署创建Jenkins docker-compose配置maven源启动Jenkins容器安装插件Gitee ssh公匙配置与测试项目提交 Jenkins创建流水线写在最后 前言 持续集成和持续交付一直是当下流行的开发运维方式&#xff0c;CICD省去了大量的运维时间&#xff0c;也能够提高开发…...

7.25 Qt

制作一个登陆界面 login.pro文件 QT core guigreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c11# The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings # depend on …...

P1420 最长连号

题目描述 输入长度为 n n n 的一个正整数序列&#xff0c;要求输出序列中最长连号的长度。 连号指在序列中&#xff0c;从小到大的连续自然数。 输入格式 第一行&#xff0c;一个整数 n n n。 第二行&#xff0c; n n n 个整数 a i a_i ai​&#xff0c;之间用空格隔开…...

UVA-1354 天平难题 题解答案代码 算法竞赛入门经典第二版

GitHub - jzplp/aoapc-UVA-Answer: 算法竞赛入门经典 例题和习题答案 刘汝佳 第二版 这道题需要&#xff1a; 1. 遍历二叉树的每种构成方式。我这里每次把当前所有结点列出&#xff0c;然后遍历选取两个组合构成一个新结点&#xff0c;原来的结点剔除&#xff0c;新结点加入。…...

电机故障诊断(python程序,模型为CNN结合LSTM)

代码运行环境要求&#xff1a;TensorFlow版本>2.4.0&#xff0c;python版本>3.6.0 运行效果视频&#xff1a;电机故障诊断&#xff08;python代码&#xff09;_哔哩哔哩_bilibili 1.电机常见的故障类型有以下几种&#xff1a; 轴承故障&#xff1a;轴承是电机运转时最容…...

ubuntu 20.04 rtc时间显示问题探究

1、硬件与软件 本次测试的硬件为RK3568芯片&#xff0c;操作系统为ubuntu 20.04。 2、RTC与系统时间 先说结果&#xff0c;如果RTC驱动不可用或者RTC内部存储的时间非法&#xff0c; 那么操作系统会存储上一次有效的时间&#xff0c;当再次上电时&#xff0c;date命令会使用存储…...

数值分析第七章节 用Python实现非线性方程与方程组的数值解法

参考书籍&#xff1a;数值分析 第五版 李庆杨 王能超 易大义编 第7章 非线性方程与方程组的数值解法 文章声明&#xff1a;如有发现错误&#xff0c;欢迎批评指正 文章目录 迭代法求解 x e x − 1 0 xe^x-10 xex−10牛顿法求解 x e x − 1 0 xe^x-10 xex−10简化牛顿法求解 …...

利用MATLAB制作DEM山体阴影

在地理绘图中&#xff0c;我们使用的DEM数据添加山体阴影使得绘制的图件显得更加的美观。 GIS中使用ArcGIS软件就可以达到这一目的&#xff0c;或者使用GMT&#xff0c;同样可以得到山体阴影的效果。 本文提供了一个MATLAB的函数&#xff0c;可以得到山体阴影。 clear all;c…...

ubuntu 使用 rsync 的 SSH 方式同步备份远程WEB服务器

ubuntu 20.04 自带 rsync &#xff0c;对于 WEB 服务器这种更新频率不高的情况&#xff0c;直接使用定时同步复制远程服务器的方法&#xff0c;比较直接和简单&#xff01; $ rsync --version rsync version 3.1.3 protocol version 31 参考&#xff1a; Ubuntu20.04中的rsyn…...

机器学习 | Python实现NARX模型预测控制

机器学习 | Python实现NARX模型预测控制 目录 机器学习 | Python实现NARX模型预测控制效果一览基本介绍研究内容程序设计参考资料效果一览 基本介绍 机器学习 | Python实现NARX模型预测控制 研究内容 贝叶斯黑盒模型预测控制,基于具有外源输入的非线性自回归模型的预期自由能最…...

M5ATOMS3基础03给ROS1发一个问候(rosserial)

引出问题 关于之前2020年的博客&#xff1a; 01. ESP8266和ROS调试一些问题汇总 02. ESP8266和ESP32配置&#xff08;需使用ROS1和ROS2&#xff09; 效果展示 使用M5ATOMS3与ROS1&#xff08;kinetic&#xff0c;melodic&#xff0c;noetic&#xff09;版本通信比较通用的是…...

基于Vue3实现鼠标按下某个元素进行移动,实时改变左侧或右侧元素的宽度,以及点击收起或展开的功能

其原理主要是利用JavaScript中的鼠标事件来控制CSS样式。大致就是监听某个DOM元素的鼠标按下事件&#xff0c;以及按下之后的移动事件和松开事件。在鼠标按下且移动过程中&#xff0c;可实时获得鼠标的X轴坐标的值&#xff0c;通过简单计算&#xff0c;可计算出目标元素的宽度&…...

使用MyBatis(2)

目录 一、定义接口、实体类、创建XML文件实现接口&#xff09; 二、MyBatis的增删改查 &#x1f345;1、MyBatis传递参数查询 &#x1f388;写法一 &#x1f388;写法二 &#x1f388;两种方式的区别 &#x1f345;2、删除操作 &#x1f345;3、根据id修改用户名 &#x…...

【FPGA/D6】

2023年7月25日 VGA控制器 视频23notecodetb 条件编译error时序图保存与读取&#xff1f;&#xff1f;RGBTFT显示屏 视频24PPI未分配的引脚或电平的解决方法 VGA控制器 视频23 note MCU单片机 VGA显示实时采集图像 行消隐/行同步/场同步/场消隐 CRT&#xff1a;阴极射线管 640…...

【WebGIS实例】(10)Cesium开场效果(场景、相机旋转,自定义图片底图)

效果 漫游效果视频&#xff1a; 【WebGIS实例】&#xff08;10&#xff09;Cesium开场效果&#xff08;场景、相机 点击鼠标后将停止旋转并正常加载影像底图&#xff1a; 代码 可以直接看代码&#xff0c;注释写得应该比较清楚了&#xff1a; /** Date: 2023-07-28 16:21…...

【Spring】IOC的原理

一、 IOC 的概念 Spring 的 IOC &#xff0c;即控制反转&#xff0c;所谓控制反转 —— 本来管理业务对象&#xff08;bean&#xff09;的操作是由我们程序员去做的&#xff0c;但是有了 Spring 核心容器后&#xff0c;这些 Bean 对象的创建和管理交给我们Spring容器去做了&am…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...

scikit-learn机器学习

# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...

C++ 设计模式 《小明的奶茶加料风波》

&#x1f468;‍&#x1f393; 模式名称&#xff1a;装饰器模式&#xff08;Decorator Pattern&#xff09; &#x1f466; 小明最近上线了校园奶茶配送功能&#xff0c;业务火爆&#xff0c;大家都在加料&#xff1a; 有的同学要加波霸 &#x1f7e4;&#xff0c;有的要加椰果…...

Git常用命令完全指南:从入门到精通

Git常用命令完全指南&#xff1a;从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...

AI语音助手的Python实现

引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...