Unreal Engine 游戏开发学习笔记 20181106


本篇博文实为在”系统”学习 Unreal Engine 4 游戏开发后整理的学习笔记。笔记按照每天的学习内容进行整理记录备忘。

本文为 Week3 Class2! 其中 表示上午的学习内容, 表示下午的学习内容。从本周开始连续三周学习 C++ 基础。同时强烈推荐像我一样的初学者看下”菜鸟教程”的 C++ 部分,本周的笔记绝大部分整理的内容均来自菜鸟笔记,只是内容按照上课老师所讲并在笔记中穿插了一些老师上课所讲实例,感谢菜鸟笔记网站管理员的无私分享。

今日内容摘要(知识点梳理):

1. 作业辅导复习
2. 枚举的补充
3. 结构体的补充
4. 类的补充知识点
5. 类及类的继承


知识点补充及类的继承

枚举的补充知识

1
2
3
4
5
6
7
8
// 枚举实际上是整数
// 默认第一个元素为0 如果指定第一个值后一个值是前一个值+1
enum EDogColor {
Black = 0,
Yellow,
White,
Red
};

结构体的知识点补充

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 结构体也是一个数据类型 既然是数据类型就能用来声明变量
struct Point
{
// 结构体的成员默认都是public的
// 属性:结构体的特征 不要初始化属性
float x;
float y;
// 平时使用结构体的时候完全可以省略构造函数,但是初始化参数就费劲了。
Point() {

};
// 构造函数传递参数的目的:初始化属性
Point(float NewX, float NewY) {
x = NewX;
y = NewY;
}

//常量函数 不改变原始数据
float GetArea() const
{
return x * y;
}

// 结构体被认为是复合数据类型(简单类型的组合)
// 结构体内可以写函数,最好不要写行为(功能)函数 功能函数写在类里 结构体内可以写简单数据处理的算法函数

};

类的一句话描述

1
2
3
4
5
6
7
8
9
// 类是描述具有相同特征和行为的一类事物,类是设计方案,蓝图,所有个体特征的描述
// 类的成员:包括数据成员(属性) 成员函数
// 类成员访问修饰符 private(私有类内部访问,想让外界访问就提供函数(public):访问和修改(定义返回值值类型一定要有return 否则必须是void)) public要在各类类成员前写好
// 函数命名 动词 + 名词 (功能函数是行为)
// 类成员: 属性本身 属性函数 一对一对的函数进行函数接口访问及设置 构造函数 析构函数 复制构造函数 功能函数
// 类必须有构造函数否则无法实例化,一个构造函数不写,系统会提供一个无参的构造函数,如果写了构造函数(带参数),无参的构造函数必须自己写入(如果你用!)。 类中的构造函数作用:1.实例化个体 2.初始化属性
// 复制构造函数 const放在类构造函数前面 表示不能修改构造函数参数,放在函数头后面表示 不修改任何属性可能只做返回使用(属性函数(读取))
// 析构函数 与 构造函数相反 构造函数开辟内存 析构函数释放内存 类里面有指针必须写析构函数
// 在行为功能函数中,如果函数类型为void,可以有return,但不能有任何值。

C++ 继承

面向对象程序设计中最重要的一个概念是继承。继承允许我们依据另一个类来定义一个类,这使得创建和维护一个应用程序变得更容易。这样做,也达到了重用代码功能和提高执行时间的效果。

当创建一个类时,您不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类,新建的类称为派生类。

继承代表了 is a 关系。例如,哺乳动物是动物,狗是哺乳动物,因此,狗是动物,等等。

基类 & 派生类

一个类可以派生自多个类,这意味着,它可以从多个基类继承数据和函数。定义一个派生类,我们使用一个类派生列表来指定基类。类派生列表以一个或多个基类命名,形式如下:

1
class derived-class: access-specifier base-class

其中,访问修饰符 access-specifier 是 public、protected 或 private 其中的一个,base-class 是之前定义过的某个类的名称。如果未使用访问修饰符 access-specifier,则默认为 private。
假设有一个基类 Shape,Rectangle 是它的派生类,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>

using namespace std;

// 基类
class Shape
{
public:
void setWidth(int w)
{
width = w;
}
void setHeight(int h)
{
height = h;
}
protected:
int width;
int height;
};

// 派生类
class Rectangle: public Shape
{
public:
int getArea()
{
return (width * height);
}
};

int main(void)
{
Rectangle Rect;

Rect.setWidth(5);
Rect.setHeight(7);

// 输出对象的面积
cout << "Total area: " << Rect.getArea() << endl;

return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

1
Total area: 35


类的多继承及虚拟继承

访问控制和继承

派生类可以访问基类中所有的非私有成员。因此基类成员如果不想被派生类的成员函数访问,则应在基类中声明为 private。
我们可以根据访问权限总结出不同的访问类型,如下所示:

一个派生类继承了所有的基类方法,但下列情况除外:

  • 基类的构造函数、析构函数和拷贝构造函数。
  • 基类的重载运算符。
  • 基类的友元函数。

继承类型

当一个类派生自基类,该基类可以被继承为 public、protected 或 private 几种类型。继承类型是通过上面讲解的访问修饰符 access-specifier 来指定的。
我们几乎不使用 protected 或 private 继承,通常使用 public 继承。当使用不同类型的继承时,遵循以下几个规则:

  • 公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。
  • 保护继承(protected): 当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员。
  • 私有继承(private):当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员。

多继承

多继承即一个子类可以有多个父类,它继承了多个父类的特性。
C++ 类可以从多个类继承成员,语法如下:

1
2
3
4
class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…
{
<派生类类体>
};

其中,访问修饰符继承方式是 public、protected 或 private 其中的一个,用来修饰每个基类,各个基类之间用逗号分隔,如上所示。现在让我们一起看看下面的实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>

using namespace std;

// 基类 Shape
class Shape
{
public:
void setWidth(int w)
{
width = w;
}
void setHeight(int h)
{
height = h;
}
protected:
int width;
int height;
};

// 基类 PaintCost
class PaintCost
{
public:
int getCost(int area)
{
return area * 70;
}
};

// 派生类
class Rectangle: public Shape, public PaintCost
{
public:
int getArea()
{
return (width * height);
}
};

int main(void)
{
Rectangle Rect;
int area;

Rect.setWidth(5);
Rect.setHeight(7);

area = Rect.getArea();

// 输出对象的面积
cout << "Total area: " << Rect.getArea() << endl;

// 输出总花费
cout << "Total paint cost: $" << Rect.getCost(area) << endl;

return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

1
2
Total area: 35
Total paint cost: $2450

虚拟继承

另外多继承(环状继承),A->D, B->D, C->(A,B),例如:

1
2
3
4
class D{......};
class B: public D{......};
class A: public D{......};
class C: public B, public A{.....};

这个继承会使D创建两个对象,要解决上面问题就要用虚拟继承格式
格式:class 类名: virtual 继承方式 父类名

class D{……};
class B: virtual public D{……};
class A: virtual public D{……};
class C: public B, public A{…..};

虚继承–(在创建对象的时候会创建一个虚表)在创建父类对象的时候

1
2
A:virtual public D
B:virtual public D

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>

using namespace std;
//基类

class D
{
public:
D(){cout<<"D()"<<endl;}
~D(){cout<<"~D()"<<endl;}
protected:
int d;
};

class B:virtual public D
{
public:
B(){cout<<"B()"<<endl;}
~B(){cout<<"~B()"<<endl;}
protected:
int b;
};

class A:virtual public D
{
public:
A(){cout<<"A()"<<endl;}
~A(){cout<<"~A()"<<endl;}
protected:
int a;
};

class C:public B, public A
{
public:
C(){cout<<"C()"<<endl;}
~C(){cout<<"~C()"<<endl;}
protected:
int c;
};

int main()
{
cout << "Hello World!" << endl;
C c; //D, B, A ,C
cout<<sizeof(c)<<endl;
return 0;
}

new 动态分配内存及内存回收

这里面使用指针的意义是因为可以使用new 函数动态的分配内存(还会在析构函数释放内存)已节省内存使用 提高提存是的使用效率


可能想问吧

今天上午讲解的主要是上午的作业辅导及函数基础,并没有很难,暂时没有想问的!


一起练习吧

用指针写两个类:

玩家类

技能类

在写一个新的类,要有两级子类



上课代码笔记

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
// 

#include "stdafx.h"
#include <iostream>
#include <string>
#include <math.h>


using namespace std;

// 作业辅导复习
// 枚举实际上是整数
// 默认第一个元素为0 如果指定第一个值后一个值是前一个值+1
enum EDogColor {
Black = 0,
Yellow,
White,
Red
};

// 结构体也是一个数据类型 既然是数据类型就能用来声明变量
struct Point
{
// 结构体的成员默认都是public的
// 属性:结构体的特征 不要初始化属性
float x;
float y;
// 平时使用结构体的时候完全可以省略构造函数,但是初始化参数就费劲了。
Point() {

};
// 构造函数传递参数的目的:初始化属性
Point(float NewX, float NewY) {
x = NewX;
y = NewY;
}

//常量函数 不改变原始数据
float GetArea() const
{
return x * y;
}

// 结构体被认为是复合数据类型(简单类型的组合)
// 结构体内可以写函数,最好不要写行为(功能)函数 功能函数写在类里 结构体内可以写简单数据处理的算法函数

};

// 类是描述具有相同特征和行为的一类事物,类是设计方案,蓝图,所有个体特征的描述
// 类的成员:包括数据成员(属性) 成员函数
// 类成员访问修饰符 private(私有类内部访问,想让外界访问就提供函数(public):访问和修改(定义返回值值类型一定要有return 否则必须是void)) public要在各类类成员前写好
// 函数命名 动词 + 名词 (功能函数是行为)
// 类成员: 属性本身 属性函数 一对一对的函数进行函数接口访问及设置 构造函数 析构函数 复制构造函数 功能函数
// 类必须有构造函数否则无法实例化,一个构造函数不写,系统会提供一个无参的构造函数,如果写了构造函数(带参数),无参的构造函数必须自己写入(如果你用!)。 类中的构造函数作用:1.实例化个体 2.初始化属性
// 复制构造函数 const放在类构造函数前面 表示不能修改构造函数参数,放在函数头后面表示 不修改任何属性可能只做返回使用(属性函数(读取))
// 析构函数 与 构造函数相反 构造函数开辟内存 析构函数释放内存 类里面有指针必须写析构函数
// 在行为功能函数中,如果函数类型为void,可以有return,但不能有任何值。


// 以下是新课

struct Location
{
float x;
float y;
float z;
Location(float NewX, float NewY, float NewZ) {
x = NewX;
y = NewY;
z = NewZ;
}
Location() {}
};

// 类是描述个体特征和行为,特征是描述个体的
// 人类:男人 女人 都有两条腿 static int LegNum = 2; 1.所有对象都拥有的特征
class Monster {

public:
string Name;
static int Counter; // 这个数据属于类 静态属性 为所有对象共同拥有的
static int Number;
protected: // 受保护的 子类可以访问修改但是外界不能访问
int Level;
Location MonsterLocation;
float AP; // 攻击力
float DP; // 防御力:魔法防御 物理防御 轻甲和重甲
float MP; // 魔法
float HP; // 生命
public:
// Level 只读属性
int GetLevel() {
return Level;
}
float GetAP() {
return AP;
}
Location GetLocation() {
return MonsterLocation;
}
void SetAP(float NewAP) {
AP = NewAP;
}

public:
Monster() {
Counter++;

};
Monster(string NewName, int NewLevel, float NewAP, float NewDP, float NewMP, float NewHP, Location NewLoc) :Name(NewName), Level(NewLevel), AP(NewAP),
DP(NewDP), MP(NewMP), HP(NewHP), MonsterLocation(NewLoc) // 初始化列表 C++ 比较喜欢
{
Counter++;

}
~Monster() {
Counter--;

}
// 虽然不写编译器会加 但有可能用到指针所以大部分人会先写
public:
// 对象函数
void Attack(Monster& Some) { // 本家怪物干别的怪物
Some.HP = Some.HP - (AP - Some.DP); // 被攻击怪物最终的血量 = 被攻击怪物的当前血量 - 自己的攻击力将去别人的防御力的差值
}
void Move(Location NewLoc) {
MonsterLocation.x = NewLoc.x;
MonsterLocation.z = NewLoc.z;
}

};

// 静态属性只能在类的外面完成初始化
int Monster::Counter = 0;



// 类的继承: 使GrantGiant继承了Monster的类
// GrantGiant 为子类,Monster为父类
// 子类拥有父类所有成员 包括数据和功能函数 但是父类不能拥有子类定义的成员
// 公开继承:子类继承的代码保持父类的访问级别 (父类是私有的继承过来也是私有的)
// 私有继承:父类中的所有成员在子类中全部变成私有的
class GrantGiant :public Monster { // public 公开继承 Monster 子类不能访问父类函数中私有数据和私有函数
public:
void RecoverHP(float DeltaHP) {
HP += DeltaHP;
}
};

class GreenPerson :public GrantGiant {

};

// 突然想起来昨晚打印a不同值了 参数传递的时候 一个打印变量一个在函数里打印了
// 这里面使用指针的意义是因为可以使用new 函数动态的分配内存(还会在析构函数释放内存)已节省内存使用 提高提存是的使用效率
class Weapon {
private:
char* Name;
int* AP;
Monster* Owner;
public:

public:
Weapon(const char* NewName, int* NewAP, Monster* NewOwner) {
int len = strlen(NewName);
Name = new char[len + 1]; // new 动态分配内存
strcpy_s(Name, len + 1, NewName);

AP = new int; //开辟 新的空间内存 只要new就要考虑什么时候释放 否则这段内存就不会被释放
*AP = *NewAP;

Owner = NewOwner;
}
~Weapon() {
delete[] Name;
Name = 0;

delete AP; // 释放内存空间
AP = 0; // 空指针 让指针不指向任何地方

}
public:
char* GetName() {
return Name;
}

};

// 此文件cout << Monster::Counter << endl << endl;打印出错,如果新创建项目可用!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


int main() {


cout << Monster::Counter << endl << endl; // 通过类型访问数据 只有在类外面才能对静态数据进行初始化
GrantGiant Hulk; // 本质上是一个变量 是GrantGiant的变量 也是GrantGiant类的一个实例 Hulk是一个具体对象(个体) 他含有所有的GrantGiant类属性
Location NewLoc(100.f, 100.f, 100.f);
Hulk.Move(NewLoc);
Hulk.RecoverHP(10.f);
Hulk.GetLevel(); // 属性函数 外部访问对象数据的接口
cout << Monster::Counter << endl << endl;
GreenPerson GP;
GP.RecoverHP(10.f);
cout << Monster::Counter << endl << endl;

Point APoint;
APoint.x = 10;

int a = 3;
// int* Pa = &a;
int* pa = new int; //new 内存中开辟一个存放整数的空间,把新空间地址返回
*pa = a; //解除对指针的引用并将a(3)赋值给pa

const char* WeaponName = "DaJian";
int AP = 10;
Monster Big;

Weapon AW(WeaponName, &AP, &Big);
cout << AW.GetName() << endl << endl;



return 0;
}




我的作业提交

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
// Week3_Class2_HomeWork.cpp: 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <string>
#include <iostream>
#include <math.h>


using namespace std;

class Player {
public:
char* Name;
protected:
int* Level;
float* HP;
float* AP;
float* DP;

public:
char GetName() {
return *Name;
}
int GetLevel() {
return *Level;
}
float GetHP() {
return *HP;
}
float GetAP() {
return *AP;
}
float GetDP() {
return *DP;
}
void SetLevel(int* NewLevel) {
Level = new int;
*Level = *NewLevel;
}
void SetHP(float* NewHP) {
HP = new float;
*HP = *NewHP;
}
void SetAP(float* NewAP) {
AP = new float;
*AP = *NewAP;
}
void SetDP(float* NewDP) {
DP = new float;
*DP = *NewDP;
}

public:
Player() {

}

Player(const char* NewName, int* NewLevel, float* NewHP) {
int Length = strlen(NewName);
Name = new char[Length + 1];
strcpy_s(Name, Length + 1, NewName);

Level = new int;
*Level = *NewLevel;

HP = new float;
*HP = *NewHP;

cout << "构造函数1调用中..." << endl << endl;
}

Player(const char* NewName, float* NewHP, float* NewAP, float* NewDP) {
int Length = strlen(NewName);
Name = new char[Length + 1];
strcpy_s(Name, Length + 1, NewName);

HP = new float;
*HP = *NewHP;

AP = new float;
*AP = *NewAP;

DP = new float;
*DP = *NewDP;

cout << "构造函数2调用中..." << endl << endl;
}

Player(const char* NewName, int* NewLevel, float* NewHP, float* NewAP, float* NewDP) {
int Length = strlen(NewName);
Name = new char[Length + 1];
strcpy_s(Name, Length + 1, NewName);

Level = new int;
*Level = *NewLevel;

HP = new float;
*HP = *NewHP;

AP = new float;
*AP = *NewAP;

DP = new float;
*DP = *NewDP;

cout << "构造函数3调用中..." << endl << endl;
}

//
Player(const Player& APlayer) {

int Length = strlen(APlayer.Name);
Name = new char[Length + 1];
strcpy_s(Name, Length + 1, APlayer.Name);

if (APlayer.Level != 0) {
Level = new int;
cout << *APlayer.Level << endl << endl;
}
else {
// 如果调用不含Level形参即指针为空,会抛出 APlayer.Level 是 nullptr。
}


HP = new float;
*HP = *APlayer.HP;

AP = new float;
*AP = *APlayer.AP;

DP = new float;
*DP = *APlayer.DP;
cout << "复制构造函数调用中..." << endl << endl;
}

~Player() {
delete[] Name;
Name = 0;
cout << "析构调用删除Name.." << endl << endl;
delete Level;
Level = 0;
cout << "析构调用删除Level.." << endl << endl;
delete HP;
HP = 0;
cout << "析构调用删除HP.." << endl << endl;
delete AP;
AP = 0;
cout << "析构调用删除AP.." << endl << endl;
delete DP;
DP = 0;
cout << "析构调用删除DP.." << endl << endl;
}

public:
void HasBeenHit() {
*HP = *HP - (*AP - *DP);
cout << "已被击中,呼呼掉血中..." << endl << endl << "当前剩余血量: " << *HP << endl << endl;
}

};

class Skill {
public:
char* Name;
int MaxLevel = 6;
protected:
int* Level;
float* AP; // 法术伤害
float* AD; // 物理伤害
float* CD; // 冷却时间
public:
char* GetName() {
return Name;
}
int* GetLevel() {
return Level;
}

float* GetAP() {
return AP;
}
float* GetAD() {
return AD;
}
float* GetCD() {
return CD;
}

void SetLevel(int* NewLevel) {
Level = new int;
*Level = *NewLevel;
}

void SetAP(float* NewAP) {
AP = new float;
*AP = *NewAP;
}
void SetAD(float* NewAD) {
AD = new float;
*AD = *NewAD;
}
void SetCD(float* NewCD) {
CD = new float;
*CD = *NewCD;
}
public:
Skill() {

}

Skill(const char* NewName, int* NewLevel, float* NewAP, float* NewCD) {
int Length = strlen(NewName);
Name = new char[Length + 1];
strcpy_s(Name, Length + 1, NewName);

Level = new int;
*Level = *NewLevel;

AP = new float;
*AP = *NewAP;

CD = new float;
*CD = *NewCD;

cout << "构造函数1调用中..." << endl << endl;
}

Skill(const char* NewName, int* NewLevel, float* NewAP, float* NewCD, float* NewAD) {
int Length = strlen(NewName);
Name = new char[Length + 1];
strcpy_s(Name, Length + 1, NewName);

Level = new int;
*Level = *NewLevel;

AP = new float;
*AP = *NewAP;

CD = new float;
*CD = *NewCD;

AD = new float;
*AD = *NewAD;

cout << "构造函数2调用中..." << endl << endl;
}

Skill(const Skill& ASkill) {
int Length = strlen(ASkill.Name);
Name = new char[Length + 1];
strcpy_s(Name, Length + 1, ASkill.Name);

if (ASkill.Level != 0) {
Level = new int;
*Level = *ASkill.Level;
}
else {
// 如果调用不含Level形参即指针为空,会抛出 Skill.Level 是 nullptr。
}

if (ASkill.AD != 0) {
AD = new float;
*AD = *ASkill.AD;
}
else {
// 如果调用不含Level形参即指针为空,会抛出 Skill.Level 是 nullptr。
}

AP = new float;
*AP = *ASkill.AP;

CD = new float;
*CD = *ASkill.CD;
cout << "复制构造函数调用中..." << endl << endl;
}

~Skill() {
delete[] Name;
Name = 0;

delete Level;
Level = 0;

delete AP;
AP = 0;

delete AD;
AD = 0;

delete CD;
CD = 0;
}
public:
void UpgradeLevesAndSubtractCD(int* NewLevel) {
float Ratio = *NewLevel / float(MaxLevel);
float OldCD = *CD;
*CD = (*CD - Ratio * *CD) + 0.3;
cout << "原始冷却时间为: " << OldCD << " 秒 " << " 当前技能冷却时间为: " << *CD << " 秒 " << endl << endl << endl << endl;
}

void PrintString() {
cout << "测试打印函数功..." << endl << endl;
}
};

enum EPerformerType {
Actor,
Actress
};

enum ERace {
YellowRace,
WhiteRace,
BlackRace
};

class Performer {

string Name;
int Age;
EPerformerType PerformerType;
ERace Race;

public:
// 属性函数
string GetName() {
return Name;
};

int GetAge() {
return Age;
};

void SetAge(int NewAge) {
Age = NewAge;
};

public:
// 构造函数
Performer()
{

}
Performer(string NewName) {
Name = NewName;
cout << "Performer构造函数1调用中..." << endl << endl;
};

Performer(string NewName, int NewAge) {
Name = NewName;
Age = NewAge;
cout << "Performer构造函数2调用中..." << endl << endl;
};

Performer(string NewName, int NewAge, ERace NewRace) {
Name = NewName;
Age = NewAge;
Race = NewRace;
cout << "Performer构造函数3调用中..." << endl << endl;
};

Performer(string NewName, int NewAge, ERace NewRace, EPerformerType NewPerformerType) {
Name = NewName;
Age = NewAge;
Race = NewRace;
PerformerType = NewPerformerType;
cout << "Performer构造函数3调用中..." << endl << endl;
};


// 复制构造函数
Performer(const Performer& APerformer) {
Name = APerformer.Name;
Age = APerformer.Age;
Race = APerformer.Race;
PerformerType = APerformer.PerformerType;
cout << "Performer复制构造函数..." << endl << endl;
}

// 析构函数
~Performer() {

}

public:
void Eat() {
cout << "行为函数调用:吃饭中...." << endl << endl;
}
void Drink() {
cout << "行为函数调用:喝水...." << endl << endl;
}
void Sleep() {
cout << "行为函数调用:睡觉...." << endl << endl;
}
};


class CActor :public Performer {
public:
void Film() {
cout << "拍摄 THE EXPENDABLES " << endl << endl;
}

};

class CActress :public Performer {
public:
void Film() {
cout << "拍摄 2 Broke Girls " << endl << endl;
}

};
class Comedian :public CActor {
public:
void PerformanceCrosstalk() {
cout << "...给大家来段贯口... 蒸羊羔、蒸熊掌、蒸鹿尾儿、烧花鸭、烧雏鸡、烧子鹅、卤猪、 卤鸭、酱鸡、 腊肉、松花小肚儿 ...\n" << endl << endl;
}
};


int main()
{
cout << "=======================================================================================================================" << endl << endl;
// 测试Player类
cout << "Player类测试: " << endl;
const char* PlayerName = "Hulk";
float HP = 100.f;
float AP = 20.f;
float DP = 10.f;
int Level = 1;

cout << endl << endl;
Player Hulk(PlayerName, &HP, &AP, &DP);

Hulk.HasBeenHit();
cout << endl << endl;
Player Thor(Hulk);
Thor.HasBeenHit();

cout << "=======================================================================================================================" << endl << endl;

// 测试Skill类
cout << "Skill类测试: " << endl << endl;
cout << endl << endl;
const char* SkillName = "降龙十八掌";
float AD = 80.f;
float CD = 3.5f;

int NewLevel = 6;
Skill RelaseSkill(SkillName, &Level, &AP, &CD);
RelaseSkill.UpgradeLevesAndSubtractCD(&NewLevel);

Skill NewRelaseSkill(RelaseSkill);

cout << *(NewRelaseSkill.GetCD()) << endl << endl;
NewRelaseSkill.PrintString();
cout << endl << endl;

cout << "=======================================================================================================================" << endl << endl;
// 测试类演员类的继承
cout << "类继承测试: " << endl << endl;
Performer FristPerformer("成龙", 64);
cout << "调用属性函数读取年龄: " << FristPerformer.GetAge() << endl << endl;
CActor AActor;
CActress AActress;

cout << endl << endl;
cout << "父类调用测试" << endl << endl;
AActor.Drink();
AActress.Eat();

cout << endl << endl;
Comedian AComedian;
cout << "父类调取测试: 大家快看喜剧演员拍<<敢死队>>电影了..." << endl << endl;
AComedian.Film();
cout << "=======================================================================================================================" << endl << endl;


return 0;
}


----------本文结束感谢您的阅读----------

本文标题:Unreal Engine 游戏开发学习笔记 20181106

文章作者:XIANVFX

发布时间:2018年11月06日 - 09:11

最后更新:2019年05月21日 - 09:05

原始链接:www.xianvfx.top/UE4/Training/Week3_CPP2/Unreal_Engine_Learning_Notes_W3_2.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

(*❦ω❦) 感谢您的支持! (*❦ω❦)
0%