c++与unreal学习
C++基础:
仅仅作为本人java开发,自学c++的学习笔记。因为有java基础,所以基础内容记录不会很详细
基础
编译器(也是开发工具):
visual studio 2017. 下载地址:https://visualstudio.microsoft.com/zh-hans/vs/community/
visual studio 基本操作:
ctrl+k,然后 ctrl+c ,行注释一段代码。 格式:// 与java相同
ctrl+k,然后ctrl+u,取消一段代码的注释。
菜鸟基础学习地址:https://www.runoob.com/cplusplus/cpp-tutorial.html
helloworld步骤:
使用visual studio新建一个空白项目,取名helloworld
在源文件处,新建项目。选择cpp文件。取名helloWorld
编写如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14// <>表示程序将会首先且只会去你的系统类库目录查找你所想引入的类或者包;
// ""表示程序会首先从你的当前目录查找你所想引入的类或者包,如果没有找到,将去系统类库目录找.
using namespace std;
int main() {
cout << "hello world" << endl;
system("pause");
return 0;
}点击本地windows调试,可以看到输出 hello world
常量
定义常量两种方式:
- #define 宏常量。 #define name value,例如:#define dayOfMonth 7
- 在变量前加 const关键字。
常量是不可以更改的。一旦修改就会报错。类似于java的final
基本数据类型
整型:int。8个字节。与java相同。并且具有构造方法
实型(浮点型): 对应java中的float,double。并与java含义相同
字符型:char,与java用法相同。字符的ascii码
转义字符:参见正则
字符串类型:因为沿用于c语言,可以直接将char数组定义为字符串。例如:char str[] = “hello world”
同时也有自己的对象风格,string str = “hello world”。需要注意,若要在代码中定义sting类型数据,需要引入头文件 #include “string”
布尔类型:bool.基本与java相同。不同的在于,在输出bool时,其实质就是一个字节。表示为1(真),或0(假)。
标准输入输出流
1 | // 在引入头文件后: |
变量
用法与java大致相同。不过c++具有指针,引用的概念,可以更自由的访问内存。
需要注意的是,当c++中, type a = b ; 的时候,会创建一个变量b的副本给a的引用。此时,a,b是两个独立的变量。各自分别改变值,对另一个没有影响。
数组
定义与java相同。每个数据类型都相同。并且需要一块连续的内存空间
声明方式:
- int arr[2] = {1,2}; 即在声明变量后加[]中括号,并且规定大小,等于号右边放入数组初始值。初始值个数不能超过规定大小,否则会报错
- int arr[2]; 声明大小,不给初始值,会默认用0填充。对象的话,会用空参数对象填充
- int arr[] = {1,2},自动推导数组长度。
需要注意的是:c++中,数组的名称的本质,其实是指向第一个元素的一个指针。所以可以用指针解引用的方式取出第一个元素。又由于数组内存空间是连续的,所以可以使用名称++,来获取下一个元素的指针.获取数组长度的方法,可以用 sizeof函数,sizeof(数组)/sizeof(数组[0]).
指针与引用:
c++中的一个难点。c++指针在32位系统下,占4个字节。在64位系统下,占8个字节,即为一个int(不管指针内存的数据类型)
指针就是指指向一块内存区域的地址,下面的代码展示指针的相关用法:
1 |
|
在变量前加 * 号,可以将其定义为指针。指针 = 引用,代表指针指向某一块引用。上面int * p ,就是定义了一个类型为int的指针。指针指向变量a所在的内存空间。这里&a就是a变量所在内存空间的引用。因为指针需要指向引用,所以等号右边就需要是一个引用;
关于引用,就是一块内存,指针就是内存地址,而上面代码中的a,就是该内存当前的名字。详细可以看下面的代码:
1 |
|
可以看到,c用的是a的引用,即c所用的内存空间,就是a所在的内存空间。所以当a改变时,c也会跟着改变。c改变时,a也会跟着改变。但是b就跟a和c没关系。只是用a的值做了个克隆构造函数,在另一块内存创建了一个新对象。
空指针:
内存条中,由操作系统所占用,我们的程序无法访问的内存区域。一般位0-255号内存。即0-255内存若要访问,就会导致空指针异常(npe)
野指针:
指向非法内存空间的指针。具体是值我们程序没有申请的内存空间,若要解引用,则会抛异常
指针取值
在有当前指针的情况下,一般是需要解引用 *p解引用来获取指针指向内存的数据。但是如果目标区域是对象,则可以用 ->来获取对象参数或者执行方法.
流程控制:for循环,while循环,if判断,三目运算法
与java一样
c++流程控制:goto关键字
可以在代码中直接跳到某个位置。实际开发中,由于代码可读性差,可以被break和continue代替等原因,不会使用。这也是java中goto作为未实现的保留关键字的原因
函数(java中的方法)
我们上面写的main函数,就是函数的一种。具有返回值,函数名,入参。并且c++中main方法需要无惨,并且返回int
函数值传递:
1 |
|
函数的引用传递:
1 | void say2(int &a) { |
函数指针传递
1 | void say3(int *p) { |
函数重载:
与java一样
默认参数:
c++中,函数的入参可以有默认值。若调用者不传对应参数,则方法会自动使用默认值。
需要注意,在声明函数的时候若使用了默认值,则在实现的时候不能有默认值。并且默认参数的函数本质是函数重载,所以有任何相同调用方法的别的函数存在,编译就会报错
占位参数
区别于java的一个点,函数的入参可以只写一个类型,而不写名称。称之为站位参数。占位参数在调用时,需要传入对应类型的站位参数来调用函数。应该是用于函数重载的
1 | void say(int a) { |
函数的声明
与函数的定义相对,在函数声明前,是无法使用的。编译器会找不到函数。若先进行声明,(无函数体,类似于java的抽象方法),下面就可以用这个方法了。然后,编译器在执行的时候,会找该方法的实现。方法声明可以多次,但是实现只能是一次。若有多次实现,会报错。
c++关键字:const
被const修饰的变量为常量,我们上面已经知道,可以作为变量。但是对于const修饰指针,以及对象,则另有说法。
const修饰指针
1 | int main(){ |
const修饰对象:
该对象及其内部属性全部不能改
常量引用:
一般情况,int &a =10,即将一个引用等于一个常量是非法的。但是可以在前面加const,来使其合法。该引用变为常量引用,无法修改内存中的值
核心
面向对象
c++中,定义类有两种方式,1. 定义结构体struct,2. 定义class。两种方式几乎没区别。在网上看到的区别为:struct默认权限类型为public,class默认权限类型为private。
c++类
1 | class MyStruct |
注意:c++类定义完后,需要加分号 ;
构造函数,析构函数:
一个类,默认会有无参构造,这个跟java一致。并且自定义有参构造,会默认覆盖无惨构造。还有一个拷贝构造入参为自己本类的类型,使用浅克隆将属性赋值到本对象.
还有一个析构函数,在对象销毁时会调用,一般用来释放内存;
初始化列表:
1 | // 是跟在构造方法后,初始化类属性的方法 |
静态成员变量与函数
属性前加static。规则与java差不多。
调用方式: 类名::成员名称
1 | class People{ |
this指针
与java的this类似。不过这里的this不是对象,而是指针。需要解引用或者使用 ->
空指针相关:
c++中,空指针是可以调用成员函数的。但是前提是需要函数中没有用到this。若用到了this,则会报异常。否则成功运行
const
const修饰函数,函数变为常函数。常函数只能调用常量(const修饰的)或者mutable修饰的变量。是为了保护对象内部的属性不被乱改
const修饰对象名称,则该对象只可以调用常函数
友元
关键字:friend. 可以声明一个类或者函数作为友元。该类或者该函数可以访问本类私有属性及函数
1 |
|
继承
类似于java继承,但是c++允许多继承。
1 | // 继承语法: |
继承也有限定。public:将父类属性及方法按照原有访问权限继承。protected:将父类public的属性以及函数改为protected继承到自身。private:将父类属性及函数继承过来,但是权限全变为private;
在单继承后,子类在不重写父类方法的情况下,调用函数是父类的函数。若重写了函数,则调用的是自己的。
若想调用父类的函数,需要 对象名.父类类名::方法名(参数);例如:
1 | class B { |
菱形继承-virtual关键字
多继承,难免会有A,B两个父类有相同的成员或者方法。并且该情况会引出父类方法实现无用的结果。
则在继承时加入virtual关键字虚继承。则在编译时不会生成父类,在执行时才会。这样,相同的数据只会有一份,按照子类为准。
virtual也可以修饰方法,称为虚方法,在父类引用指向子类实例时,c++中,调用父类引用的方法,会执行父类实现。若方法为虚方法,则类中会存储虚基类指针,调用父类引用子类实现的对象的方法,会调用子类函数。
1 | virtual void say() = 0; |
函数模板 类模板
java中的泛型。其实java的泛型就是从c++的模板变过来的。
1 | // 语法 |
基本语法如上。大致上跟java里差不多。
方法模板中,可以根据入参来自动判断模板类型。而类没有自动判断。
类模板可以 class T = int 来指定默认值;若类模板函数在类外实现,需要在实现前加上模板声明
运算符重写
运算符:==,>>,<<,() 都可以重写。返回值类型 operator==(入参){方法体}
1 | // 重写== (可以类比于java重写equals),在类内 |
分文件编写
在前面讲到了,c++可以是先写好方法定义,然后去实现的。平时开发习惯将类声明以及类方法实现放在两个不同文件,声明为.h后缀的头文件,一般放属性,以及函数定义。实现是.cpp后缀的实现,引入对应头文件来编写方法实现。
需要注意的是,若类模板份文件编写,则要注意类模板函数是在执行的时候生成的。导致引入头文件不会导入函数,编译器会不认得这个函数。cpp实现文件自然也加载不到。
STL
类比于java的容器。有list,map,set等。主要是使用模板技术。
stl主要分为:容器,迭代器,算法,仿函数,适配器,空间配置器。
迭代器
大部分容器使用.begin()方法会获取迭代器的开始指针,解引用后可以获得该处对象
容器
vector容器–单边数组
类比于java的list;
1 | // 基本使用 |
常用函数 api:
1 | // 重写运算符 = 用来初始化一个集合 |
deque -双端数组.可头插可尾插
常用api:
1 | push_front(ele);// 数组前段插入元素 |