C++游戏开发小笔记

news2024/11/19 17:46:08

1.入门小语法

1.1 命名空间

当想使用库文件的某个函数时,为了防止由于重名而引起的混乱调用,使用命名空间来区分同名函数。

字符串String也是标准命名空间的一个。如果没有using namespace std;

想用string 类型得    std:: string

1.2浮点数的存储

如果定义7298为一个浮点数,那么计算机存储它时,会自动将它存储为7.298 e3

1.3 作用域

一个大的花括号被称之为一个块,这个块被称作一个作用域,如果在这个块里声明一个变量,该变量只在这个花括号里有用。

 如果该变量定义在main函数外,则它的作用为全局。

1.4 变量命名规则

 C++的关键字有以下几个

variable

type

function

namespace

template

class

1.5 引用 

当写成int &时,我们可以修改外面那个变量的值。

这里和指针还是有一点区别的。

引用就是对内存的操作。

 例如 

int b=1;

int & aa=b;

aa=2;

cout<<b<<endl;

输出的结果为2.

b的值也会改变,这个引用相当于指向那块内存。

引用的作用就是改变函数外变量的值

C++通过函数传对象的时候,改变对象里的属性值,如果不用引用,没办法把这个值传出去。 

1.6 函数重载

就是根据传进来的参数自动选择类型,函数名相同才能重载。

可以根据数据传进来的类型来选择执行方法。

1.7 字符串

引入了#include<string> 我们可以用+号来连接字符串了。

1.8 枚举类型

一个人物可能有很多种状态

 里面的实际上从第一个开始都是常量,如果不赋值,默认为第一个为0,第二个为1,默认以此叠加。

如果第一个赋值为1,后面不给值,则默认增加1。

 

这里面的变量实际上是常量的别名。

 定义一个枚举类型变量,并给它赋值,它的赋值必须得是枚举类里声明的常量,不能直接赋值为1。

然后我们可以在switch里面使用这个枚举类。完成动作设计。 

1.8.1 同名枚举类属性区分

如果两个枚举类里的变量同名,我们调用的时候需要区别对待。

 1.9 指针

指针可以提高效率,加快速度。

为什么说它高效呢?

结构体的定义和赋值占用很多字节的空间。

因为我们的方法里如果需要一个类似learn(Student stu),需要创建一个临时结构体类型局部变量Student来传进我们的函数中,这样无疑是多花费空间。

我们要做的就是传地址进函数,指针是有类型的,当你用*读该指针的地址时,就会读到同样类型长度的变量。

2 类和对象

C++类里的属性和方法默认是private私有的,想在别的地方调用方法,需要放在公共空间。

结构体里的默认权限为public

类内初始化变量,必须得用const。

 

2.1 类和结构体的区别

2.1.1 C和C++中结构体的区别

(1)C语言中的结构体不能为空,否则会报错

        C语言中要求一个结构或联合至少有一个成员。C语言中,空结构体的大小为0,而C++中空结构体(属于空类)的大小为1

(2)C语言中的结构体只涉及到数据结构,而不涉及到算法

     在C语言中数据结构和算法是分离的。换句话说就是C语言中的结构体只能定义成员变量,但是不能定义成员函数

     然而在C++中既可以定义成员变量又可以定义成员函数, C++中的结构体和类体现了数据结构和算法的结合

     不过虽然C语言的结构体中不能定义成员函数,但是却可以定义函数指针,不过函数指针本质上不是函数而是指针,所以总的来说C语言中的结构体只是一个复杂数据类型 ,只能定义成员变量,不能定义成员函数,不能用于面向对象编程

(3)C语言中定义结构变量时不可省略struct关键字,C++可以省略

        在C语言中使用struct定义的结构体中在定义变量的时候,struct不能省略

但是在C++之中则可以省略struct

2.1.2 C++中结构体和类的区别

        C++中的struct对C中的struct进行了扩充,它已经不再只是一个包含不同数据类型的数据结构         了,它已经获取了太多的功能

struct能包含成员函数吗? 能!
struct能继承吗? 能!!
struct能实现多态吗? 能!!!
既然这些它都能实现,那它和class还能有什么区别?

最本质的一个区别就是默认的访问控制: 

默认的继承访问权限:struct是public的,class是private的

C++中,不使用结构体丝毫不会影响程序的表达能力。C++之所以要引入结构体,是为了保持和C程序的兼容性

但有时仍会在C++中使用结构体,是因为可以使用结构体将不同类型数据组成整体,方便于保存数据(若用类来保存,因类中成员默认为私有,还要为每个数据成员特定函数来读取和改写各个属性,比较麻烦)

struct可以继承class,同样class也可以继承struct

struct是一种数据结构的实现体,虽然它是可以像class一样的用。我依旧将struct里的变量叫数据,class内的变量叫成员,虽然它们并无区别

2.1.3 总结
 

概念:class和struct的语法基本相同,从声明到使用,都很相似,但是struct的约束要比class多,理论上,struct能做到的class都能做到,但class能做到的stuct却不一定做的到
类型:struct是值类型,class是引用类型,因此它们具有所有值类型和引用类型之间的差异
效率:由于堆栈的执行效率要比堆的执行效率高,但是堆栈资源却很有限,不适合处理逻辑复杂的大对象,因此struct常用来处理作为基类型对待的小对象,而class来处理某个商业逻辑
关系:struct不仅能继承也能被继承 ,而且可以实现接口,不过Class可以完全扩展。内部结构有区别,struct只能添加带参的构造函数,不能使用abstract和protected等修饰符,不能初始化实例字段

牛人总结:

(1) 在表示诸如点、矩形等主要用来存储数据的轻量级对象时,首选struct

(2) 在表示数据量大、逻辑复杂的大对象时,首选class

(3) 在表现抽象和多级别的对象层次时,class是最佳选择
 

2.2 声明对象时,在构造器里完成有些属性的初始化。

这样可以在该对象被创建的时候,就发出叫的动作。这里跟java一样

 2.2.1 在类外解释类的方法

用双冒号,来编辑类或结构体里的方法。

 

结构体也可以这么写构造函数。 

 

不加返回值类型的是构造函数。在声明对象时,构造函数会启动。 

2.3 继承

C++的继承类书写。

 继承可以有3个keyword,public,protected和private。

使用public构建子类时,原封不动的继承父类的变量与函数的访问级别。

使用protected构建子类时,父类中任何的public级别的变量和函数,在子类中都将变成protected级别。

 2.3.1 继承带来的性质

当创建子类对象时,自动执行父类的构造方法(空参构造方法)。

在传参数进子类带参构造方法中,想要用父类的带参构造方法,

 直接在里面调用父类的带参构造方法。

但是如果我在声明子类对象时,不想自动执行父类的构造方法呢?

在子类的构造方法后冒汗,指明我们要用的父类构造方法,这样就不会执行空参的。

 2.3.2 类里修饰符的访问限制

类里的东西默认private。即使是对象想访问方法,也不行,如果对象非要访问,

那就把这个方法放入public空间。

 

protected比private高级一点,private只能在类里访问属性和方法。

该类的子类可以访问父类的protected空间的方法。

2.3.3 封装思想

pirvate的东西,用 set get的方法操作private属性的值。

3 栈和堆

3.1 栈stack

程序的执行是在栈里。比如进入main之后执行子程序,然后子程序的地址就会入栈,子程序里的局部变量就会入栈,该局部变量失效或者说使用完毕,就会返回地址给function1,然后function1执行完毕,返回地址给main函数。

程序在运行的过程中,栈在不断的增加和删除东西。

 3.2 堆heap

使用动态分配的内存。用完之后一定要自己手动释放。

我们在申请一个new int 空间时,里面可能有垃圾数据,这个时候得初始化来覆盖。

p这里是一个地址。 

 

 

 3.2.1 动态释放内存

释放冻结内存,但不会抹去该内存上的数据。可以让这块地址被其他子程序用来存放变量。

这个函数每次被调用都会重新申请一块空间。当程序结束时,p在栈上,会被释放,但是这个空间不会被释放。

 如果我们使用了关键字delete,那么p就会指向空。如果我们还对p进行 *p操作,那就会出现空指针异常。我们可以让p指向nullptr关键字。或者让p=0,让p指向0内存地址,但是这样容易被误解

而且可能会在重载的时候发生错误,比如让p=0了之后,将指针p传入方法,方法重载时可能分配给int类型参数的。

 4 析构函数

有时对象在被销毁时,同时也需要一些操作。可以来清在对象创建时,或者对象在生命周期内所作的任何事情。

构造函数前面有个波浪线。当delete该对象时,就执行析构函数。 

4.1 对象在建立的过程中内存的变化。

比如 man * p=new man();

1.p放在栈上,new申请的空间地址返回给p,然后构造器

2.构造器为里面的变量动态分配内存。

3.当该空间被delete时,调用析构函数,释放成员变量所占内存。

4.2 析构函数的实战操作

delete关键字触发析构函数。

析构函数会在它的作用域结束时运行。

比如这题的作用域是一个花括号

 

而如果我们这里定义一个静态类变量,会发现,当{}结束后,也不会执行析构函数。 

 5 静态变量

5.1位于函数中的 静态变量

如果在一个方法里声明一个静态变量。这种类型的变量在函数结束后仍然存在。

它只会被初始化一次,独立于函数存在。

5.2 静态类对象

比如这个dog对象不是静态的,当花括号结束了,这个变量超出作用域,即将被删除。

可是它是一个静态对象,当花括号结束了,它依然存在。

直到主函数结束,它才会被删除

5.3 放在类里的静态变量

类里的静态变量,都是独立于类对象独立存在的。

即使创建10几个对象,该变量只存在一个。

 比如这个静态变量,增加的写在构造器里,每创建一个对象,它就会增加1,类似于游戏的玩家数量。

因为这个变量只属于类,不属于任何一个对象,所以得在类外初始化它。

 

 5.4 静态函数

如果一个类里有静态函数,那么直接.以下就可以调用该函数,不用创造对象。

6 重写继承的方法

为了能让函数在不同的派生类中有不同的版本。我们把这个函数设置为虚函数。

可以让子类相同的函数与父类相同的函数有不同的功能。

在子类中我们没有必要再给他定义成virtual,因为它已经继承了父类的virtual权限。 

为了方便标识,我们可以多写一个override关键字来标识这是一个重写的方法。 

但是如果我想调用它父亲版本的这个函数呢?

方式1:在调用子类重写方法时,同时也调用父类的这个方法,通过完全限定的调用。

 

 

7 多态

多态跟继承有关。

用父类的指针指向子类的实例

如果调用相同的函数(这个函数子类也重写了),即便用父类的指针调用这个同名的方法,使用的确是子类实例里的方法。用*号或者用->

一个方法,可以实现同一继承方法的不同作用。

8 多继承

菱形继承,A和B都继承自P,都有各自的f函数。

但C同时继承了A和B这两个类,那现在C想用这个f函数,该怎么办呢? 

8.1 方法一,完全限定指明

这样通过完全限定,则可指定用哪个父类的函数。

 8.2 方法二,虚继承

为了解决多继承时的命名冲突和冗余数据问题,C++ 提出了虚继承,使得在派生类中只保留一份间接基类的成员。

 

 具体操作如下

//间接基类A
class A{
protected:
    int m_a;
};

//直接基类B
class B: virtual public A{  //虚继承
protected:
    int m_b;
};

//直接基类C
class C: virtual public A{  //虚继承
protected:
    int m_c;
};

//派生类D
class D: public B, public C{
public:
    void seta(int a){ m_a = a; }  //正确
    void setb(int b){ m_b = b; }  //正确
    void setc(int c){ m_c = c; }  //正确
    void setd(int d){ m_d = d; }  //正确
private:
    int m_d;
};

int main(){
    D d;
    return 0;
}

比如这俩类

比如istream和ostream都有方法f(),

iostream最终只保存了一份方法 f()。节省空间。

9 动态强制类型转换

9.1 隐式转换:编译器的转换

比如 float f=5.0; int a=f; 这个时候就发生了隐式转换。

9.2 显式类型转换

C+可以用C里的强转。但是C风格的强转不会考虑数据的完整性

 9.2.1 C+里的动态类型转换(向上转型)

一般用于派生链(即继承关系)

举个例子,继承关系如下。

 向上转型时(即像基类转型)有两种方法

 这两种使用运算符号dynamic_cast+,尖括号里指明目的类型<p*>。将c转成p类型。

或者用多态来转型。

9.2.2  C+里的动态类型转换(向下转型)

把p类型的转成A类型只能这么转。

 这种情况可能会出现转换失败,因为A可能不适合做p的基类。

如果转换不成功会返还一个null。

9.2.3  C+里的动态类型转换(交叉转型)

因为强制类型转换使用运行时的信息,有的编译器就要求打开

运行时类型信息:RTTI :Run-Time  Type Identification,来方便强转型的工作。

10 静态强制类型转换(static_cast关键字)

动态强制类型转换工作时,必须使用RTTI,来保证强转的合法性。适用于存在继承关系的类型转换。

非多态就没有虚函数,用static_cast可以在派生链中将一种指针转成另一种指针。

静态强制类型转换,不需要RTTI

11 constant-cast

比如有一个constant int类型的变量或表达式(这个变量或者表达式一开始的时候就不是constant类型),把它转成int类型的。

12 reinterpret-cast

它不需要检查任何东西,想往哪转往哪转(所以十分危险)

13 头文件

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/585.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机视觉--flask部署 目标检测算法,并在局域网内远端访问

1.flask框架 Flask是一个轻量级的基于Python的web框架。static 文件夹来保存静态文件&#xff0c;templates 文件夹存放前端页面 安装&#xff1a; pip install Flask框架代码&#xff1a; from flask import * from flask import Flaskapp Flask(__name__) //获取实例app.…

Web监听器:Listener

Listener简介常用监听接口监听在线用户信息的实现Model层Controller层OnlineUserListener的实现View层测试简介 监听器&#xff08;Listener&#xff09;&#xff0c;是一个实现特定接口的普通Java程序&#xff0c;用于监听Web应用中的对象或信息发生改变时&#xff0c;作出相应…

大前端进阶

目录 1.概述和前端工具vscode安装 1.下载安装VScode 2.中文界面配置 3.插件安装 4.设置字体大小 5.开启完整的Emmet语法支持 2.Nodejs 1.Nodejs介绍与安装 2.快速入门-Hello World 3.Node - 实现请求响应 4.Node-操作MYSQL数据库 3.Es6 1.ES6的概述 2.ES6的语法…

Docker实战:使用Dockerfile部署第一个netcore程序

目录 1、创建一个NetCore API项目 2、云服务部署 2.1 首先登录云服务器创建一个测试目录 2.2 新建dockerfile文件用来构建镜像。 2.3 构建镜像 2.4 运行镜像 目录 1、创建一个NetCore API项目 2、云服务部署 2.1 首先登录云服务器创建一个测试目录 2.2 新建dockerfil…

Python3,10h行代码,制作艺术签名,从此走上人生巅峰。

制作艺术签名1、引言2、代码实战2.1 代码示例3、总结1、引言 小鱼&#xff1a;小屌丝&#xff0c;你在画啥呢&#xff1f; 小屌丝&#xff1a;… 我这在练习签名呢。 小鱼&#xff1a;这… 艺术签&#xff1f; 小屌丝&#xff1a;喔&#xff0c;鱼哥&#xff0c;你这真实博才多…

CSDN云IDE怎样克隆代码

文章目录1、怎样从GitHub导入项目&#xff1f;1.1、系统生成SSH-KEY2、克隆代码2.1、克隆代码方式一2.2、克隆代码方式二2.3、克隆代码方式三1、怎样从GitHub导入项目&#xff1f; 1.1、系统生成SSH-KEY 1、打开Terminal 2、查看是否存在现有的ssh密钥 $ ls -al ~/.ssh3、检…

【LeetCode】【二叉树的最近公共祖先】

力扣 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一个节点也可以是它自…

《JavaSE-第十四章》之文件(一)

前言 在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!” 博客主页&#xff1a;KC老衲爱尼姑的博客主页 博主的github&#xff0c;平常所写代码皆在于此 刷题求职神器 共勉&#xff1a;talk is cheap, show me the code 作者是爪哇岛的新手&#xff0c;水…

Go 语言中的并发编程(Let‘s Go 二十八)

Go从底层就支持并发编程&#xff0c;同时实现垃圾回收机制。 先了解并发相关的几个名词概念。 进程&#xff1a;系统进行资源分配和调度的基本单位&#xff0c;使系统结构的基础&#xff0c;它是一个实体。 线程&#xff1a;是程序中一个单一的顺序执行流程&#xff0c;是进程…

python做了个自动关机工具,再也不会耽误我下班啦

上班族经常会遇到这样情况&#xff0c;着急下班结果将关机误点成重启&#xff0c;或者临近下班又通知开会&#xff0c;开完会已经迟了还要去给电脑关机。 【阅读全文】 今天使用PyQt5做了个自动关机的小工具&#xff0c;设置好关机时间然后直接提交即可&#xff0c;下班就可以…

什么是JWT及在JAVA中如何使用?

目录 1、为什么使用JWT? 2、JWT 的 格式 3、使用 JWT 就绝对安全 吗&#xff1f; 4、JWT 的 鉴权 流程 5、JWT 入门案例 5.1 引入依赖 5.2 生成Token 5.3 解析Token 5.4 工具类 JSON Web token简称JWT&#xff0c; 是用于对应用程序上的用户进行身份验证的标记。 也就…

测试中台初始设置

1.0 测试资源池 存在测试资源之后&#xff0c;将测试资源进行统一的管理&#xff0c;针对不同的测试场景和目的来定义不同的测试环境。将测试资源进行组合&#xff0c;测试平台可以对测试资源池进行统一的功能。 2.0 可用性测试及冒烟测试 可用性测试和冒烟测试都是快速验证…

基于Ubuntu搭建CTFd平台(全网最全)

前言&#xff1a; 最近在看《CTF安全竞赛入门》这本书&#xff0c;里面提到了搭建CTFd平台用于练习&#xff0c;学者可以在本地虚拟机上搭建。 所需系统&#xff1a;Ubuntu20.04 怎么安装虚拟机和配置Ubuntu这里就不再赘述了。 记得给Ubuntu配置VM tools1&#xff0c;方便把w…

软考中级(软件设计师)——面向对象程序设计(C++Java二选一的题15分-目标3分)

软考中级(软件设计师)——面向对象程序设计(C&Java二选一的题15分-目标3分) 目录 软考中级(软件设计师)——面向对象程序设计(C&Java二选一的题15分-目标3分) C语法要点 C类的定义&#xff1a; C派生类的定义&#xff1a; C类的外定义函数&#xff1a; C虚函数与…

Python Flask框架-开发简单博客-开篇介绍

作者&#xff1a;Eason_LYC 悲观者预言失败&#xff0c;十言九中。 乐观者创造奇迹&#xff0c;一次即可。 一个人的价值&#xff0c;在于他拥有的&#xff0c;而不是他会的。所以可以不学无数&#xff0c;但不能一无所有&#xff01; 技术领域&#xff1a;WEB安全、网络攻防 关…

PHP基础学习第十六篇(了解数组、创建数组、数组排序、总结数组的使用)

一、什么是数组 数组是一个能在单个变量中存储多个值的特殊变量。 如果有一个项目清单&#xff08;例如&#xff1a;序号名单&#xff09;&#xff0c;将其存储到单个变量中&#xff0c;如下所示&#xff1a; $a1;$b2;$c3; 然而&#xff0c;如果想要遍历数组并找出特定的一…

School assignment

目录 一、常用控制类汇编指令 二、编程实现统计寄存器AX中“1”和“0”的个数 三、编程实现从键盘输入10个1位整数 四、编程实现从键盘输入两个10进制的2位整数的和 五、编写程序练习直接、间接、相对、基址变址寻址 一、常用控制类汇编指令 MOV 传送字或字节. MOVSX 先…

JVM虚拟机

"天下事有难易乎&#xff1f;为之则易&#xff0c;不为则难" 一、初识JVM JVM是一个跨语言的平台&#xff0c;为那些能够跨平台运行的程序提供一个平台&#xff0c;JVM本身与java语言没有必然的联系&#xff0c;它只与特定的二进制文件格式.class文件所关联&#xff…

人生重开模拟器(Python实现)

文章目录人生重开模拟器介绍代码实现打印初始界面设置初始属性设置角色性别设置角色出生点针对每一岁&#xff0c;生成人生经历人生重开模拟器介绍 人生重开模拟器是由VickScarlet上传至GitHub的一款简单的文字网页游戏。 玩家点击“立即重开”并设置角色的初始属性后&#xf…

HTML 学习总结

超级详细的 HTML 学习笔记&#xff0c;一篇入门系列&#xff01;&#xff01;耐心读一遍 复习必备&#xff01;&#xff01; 目录 简要 认识标签 基本结构 常见标签 1. 注释 ---> ctrl / 2. 标题标签 ---> h1 h2 h3 h4 h5 h6 3. 段落标签 ---> p 4. 换行 ---> br …