Bingo, Computer Graphics & Game Developer

1.基类指针强制类型转换为派生类指针,其实质是辨认空间变大了,和它具体指向的内容无关

2.辨认空间变大会对指向内容的连续内存空间产生影响

Demo1

此处a的内存申请已经完成 如下图 同时也赋值成功

Demo2

此处base指针初始化时指向的是对象b

结论

内存一旦被申请之后就会被操作系统认定为受保护的 也就不会被二次申请

但辨认空间发生变化的确会引来不少的问题 在初始化以及强制类型转换基类指针的时候需要格外注意



当一个头文件被包含的同时也引入了新的依赖, 一旦该头文件被修改, 代码就会被重新编译. 

如果这个头文件又包含了其他头文件, 这些头文件的任何改变都将导致所有包含了该头文件的代码被重新编译. 因此, 我们倾向于减少包含头文件, 尤其是在头文件中包含头文件.

使用前置声明可以显著减少需要包含的头文件数量. 举例说明: 如果头文件中用到类 File, 但不需要访问 File 类的声明, 头文件中只需前置声明 class File; 而无须 #include "file/base/file.h".

不允许访问类的定义的前提下, 我们在一个头文件中能对类 Foo 做哪些操作?

我们可以将数据成员类型声明为 Foo * 或 Foo &.

我们可以将函数参数 / 返回值的类型声明为 Foo (但不能定义实现).

我们可以将静态数据成员的类型声明为 Foo, 因为静态数据成员的定义在类定义之外.

反之, 如果你的类是 Foo 的子类, 或者含有类型为 Foo 的非静态数据成员, 则必须包含 Foo 所在的头文件.


第一个原则应该是,如果可以不包含头文件,那就不要包含了。这时候前置声明可以解决问题。如果使用的仅仅是一个类的指针,没有使用这个类的具体对象(非指针),也没有访问到类的具体成员,那么前置声明就可以了。因为指针这一数据类型的大小是特定的,编译器可以获知。


第二个原则应该是,尽量在CPP文件中包含头文件,而非在头文件中。假设类A的一个成员是是一个指向类B的指针,在类A的头文件中使用了类B的前置声明并便宜成功,那么在A的实现中我们需要访问B的具体成员,因此需要包含头文件,那么我们应该在类A的实现部分(CPP文件)包含类B的头文件而非声明部分(H文件)。



模板为C++提供了泛型的概念

1.在编译初期 编译器并不会给template<typename T> fun分配内存空间 只有在发现程序显式的实例化了这个模板的时候 才会分配响应的内存出来

2.模板也会有不足的时候





比如在对比大小的min()当中

template<typename T>
T& min(const T& a, const T& b)
{
     return (a<b) ? a : b;
}

当中 会出现一定情况的不适用 比如用户想要使用char*来对比每一位大小时 编译器发现char*并没有重载过 > 或者 <运算符 那么就会出现编译无法通过的错误

template<> //告诉了编译器 这是一个模板的特化
const char* min<char *>(const char* const& a, const char* const& b)
{
     return (strcmp(a, b) < 0) ? a : b;
}

定义完之后 min就可以额外的支持基本数字类型之外的char*型了

const char* s1=“say”, s2 = "hello";
min(s1, s1) << endl;  //此时用户在程序外部调用

就可以正常的通过编译

因此模板的特化就是模板本身泛型能力不够的一种补充



1.defendor

2.attacker
包含trace和animation两内存块
–>setup(trace, animation)初始化预设动画和预设路径
–>update(skill)根据遍历一遍skill来更新自身的激活与否状态 外部通过查阅其状态来确定是否弹出vector
–>draw()

3.skill
自身具备TRACK PATH SCOPE其中scope并非一个真正意义上的技能而是直接由defendor来控制attacker的血量扣除

–path会根据自身初始化的target位置确定线性方向 之后只需要根据预设定的velocity来不断更新position即可

–track会不断的追踪某一个特定的attacker来不断的更新自身的direction(normalize之后缩放velocity大小)更新posotion
直到attacker检测到AABB碰撞之后就从vector弹出vector

–scope的skill意味着defendor不会在skill的vector当中添加一个新的技能 而是直接对当前选择的attacker进行伤害的扣除 可选的可以添加噪声以及随机

4.trace
–维护一段vector专门用于存放拐点
通过turnLeft turnRight go…等来智能的(也就是根据当前direction来判断左右转前后转需要rotate的角度)addTurningPoint达到路径中拐点的设置
之后attacker只需要不断的从vector中取得下一拐点就可以设定前进方向

5.animation
–维护一段vector专门用于存放image帧动画
只需要不断循环的从vector中读取image并渲染出来就可以做到动画播放的目的
getFrame()能返回当前播放帧的image



###初始化:

在创建项目的目录中执行git init
被init的文件夹即作为工作目录树,存放从版本库检出的代码。


###添加文件:

创建代码文件以及其他文件,通知git跟踪这个文件:
git add <文件名(可以使用统配)>


###修改以及提交:

git commit [-m “提交消息”]
git将会把提交者的姓名邮件以及-m提交消息全部提交到记录中。
使用git log来察看提交信息

使用git status来察看工作目录树的状态,即当前的视图状态。

在修改目录之后,再次使用git add来暂存更改,等待提交。
git commit接受任意多个-m参数,每次新启一段 。

git log -<数字>通过修改数字来限制命令git log输出的提交条目的个数。


###理解使用分支:

使用git branch 分支名 父分支名 来创建一个分支。
默认的主分支叫做master,这也是Git的默认的分支,master对应于CVS
和Subversion的主干(trunk)。
使用git checkout 分支名 来切换到指定的分支。


###发布分支(release branch)

在git commit中使用-a参数来告诉git提交全部修改的文件。

使用git branch命令来察看当前分支。

注意:在刚刚init初始化之后没有跟踪任何文件之前,master分支是不存在的。
git branch -d xxxxx 删除本地分支,被删除分支必须不是当前所在分支。
git branch -a察看远程分支。


###处理发布:

使用git tag <分支名> 来对指定的分支添加一个tag。使用git tag可以察看当前所有的tag。

添加标签之后,只要标签还在,从标签到版本树起点的一连串提交记录就都还在。这是可以删除打了标签的分支,这仅仅只是删除了标签的名字,而没有删除分支上的内容。

使用git rebase <分支名> 来变基,即把一个分支上的所有修改都合并到某一个分支上。比如在master分支执行git rebase test,就会把所有test分支的改动全部合并到master主分支上。
可以从一个tag建立一个分支git branch XXX


###归档:

使用git archive 命令来归档,可以创建一个gzip压缩文件。命令如下:

git archive --format=tar\
                 --prefix=<压缩包要存放的目录>/ <要归档的标签名称> \
                 | gzip > <压缩包名称>.tar.gz


git archive --format=zip\
                 --prefix=<压缩包要存放的目录>/ <要归档的标签名称> \
                 > <压缩包名称>.zip

(\表示本行命令未完,下行继续)

克隆远程版本:

使用git clone <源> 来将远程代码拷贝到本地目录。



Bingo

@BentleyJobs

Graduated from JNU, interested in cg & game developing, once worked in Aurogon to develope GuJianOL. See about for more info.