C++游戏开发小笔记

1.入门小语法

1.1 命名空间

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

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

想用string 类型得    std:: string

1.2浮点数的存储

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

1.3 作用域

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

C++游戏开发小笔记_第1张图片

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

1.4 变量命名规则

C++游戏开发小笔记_第2张图片

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

variable

type

function

namespace

template

class

1.5 引用 

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

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

引用就是对内存的操作。

C++游戏开发小笔记_第3张图片

 例如 

int b=1;

int & aa=b;

aa=2;

cout<

输出的结果为2.

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

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

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

C++游戏开发小笔记_第4张图片

1.6 函数重载

就是根据传进来的参数自动选择类型,函数名相同才能重载。C++游戏开发小笔记_第5张图片

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

1.7 字符串

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

1.8 枚举类型

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

C++游戏开发小笔记_第6张图片

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

C++游戏开发小笔记_第7张图片

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

 

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

C++游戏开发小笔记_第8张图片

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

C++游戏开发小笔记_第9张图片

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

1.8.1 同名枚举类属性区分

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

C++游戏开发小笔记_第10张图片

 1.9 指针

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

为什么说它高效呢?

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

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

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

2 类和对象

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

结构体里的默认权限为public

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

C++游戏开发小笔记_第11张图片

 

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一样

C++游戏开发小笔记_第12张图片

 2.2.1 在类外解释类的方法

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

 C++游戏开发小笔记_第13张图片

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

 C++游戏开发小笔记_第14张图片

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

C++游戏开发小笔记_第15张图片

2.3 继承

C++的继承类书写。

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

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

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

C++游戏开发小笔记_第16张图片

 2.3.1 继承带来的性质

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

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

C++游戏开发小笔记_第17张图片

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

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

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

C++游戏开发小笔记_第18张图片

 2.3.2 类里修饰符的访问限制

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

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

C++游戏开发小笔记_第19张图片

 

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

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

2.3.3 封装思想

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

3 栈和堆

3.1 栈stack

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

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

C++游戏开发小笔记_第20张图片

 3.2 堆heap

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

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

C++游戏开发小笔记_第21张图片

p这里是一个地址。 

 

 C++游戏开发小笔记_第22张图片

C++游戏开发小笔记_第23张图片

 3.2.1 动态释放内存

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

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

C++游戏开发小笔记_第24张图片

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

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

C++游戏开发小笔记_第25张图片

 4 析构函数

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

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

C++游戏开发小笔记_第26张图片

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

比如 man * p=new man();

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

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

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

4.2 析构函数的实战操作

delete关键字触发析构函数。

C++游戏开发小笔记_第27张图片

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

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

 

C++游戏开发小笔记_第28张图片

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

C++游戏开发小笔记_第29张图片

 5 静态变量

5.1位于函数中的 静态变量

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

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

5.2 静态类对象

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

C++游戏开发小笔记_第30张图片

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

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

5.3 放在类里的静态变量

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

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

C++游戏开发小笔记_第31张图片

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

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

 C++游戏开发小笔记_第32张图片

 5.4 静态函数

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

6 重写继承的方法

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

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

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

C++游戏开发小笔记_第33张图片

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

C++游戏开发小笔记_第34张图片

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

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

C++游戏开发小笔记_第35张图片

 

 

7 多态

多态跟继承有关。

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

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

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

8 多继承

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

C++游戏开发小笔记_第36张图片

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

8.1 方法一,完全限定指明

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

C++游戏开发小笔记_第37张图片

 8.2 方法二,虚继承

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

C++游戏开发小笔记_第38张图片

 

 具体操作如下

//间接基类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;
}

比如这俩类

C++游戏开发小笔记_第39张图片

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

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

9 动态强制类型转换

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

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

9.2 显式类型转换

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

C++游戏开发小笔记_第40张图片

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

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

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

C++游戏开发小笔记_第41张图片

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

C++游戏开发小笔记_第42张图片

 这两种使用运算符号dynamic_cast+,尖括号里指明目的类型。将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 头文件

C++游戏开发小笔记_第43张图片

 

你可能感兴趣的:(c++,开发语言)