找回密码
 立即注册
查看: 305|回复: 1

C++ For Unreal

[复制链接]
发表于 2023-3-25 16:13 | 显示全部楼层 |阅读模式
虚幻的编译实在是太久了,等待编译太折磨人了
趁代码编译就写点东西吧,不知道能不能帮助到别人,就当对自己的知识点做梳理了吧
第一篇就先梳理一下进入虚幻引擎必须掌握的C++基础知识吧


1.空指针/野指针

空指针

    空指针的定义:指针变量指向内存中编号为0的空间
    空指针是用来初始化指针变量的
    指针指向的内存是不可访问的
野指针

    他的定义是:指针变量指向非法的内存空间
2.指针和函数

利用指针作函数参数,可以修改实参的值
#include <iostream>
using namespace std;

int temp = 100;

void testFun(int* a)
{
        *a = temp;
}

int main(int argc, char *argv[]) {
       
        int a = 0;
        int* pa = &a;
        testFun(pa);

        cout << a << endl;       
}
指针分为两种,一种是原始指针,一种是智能指针,要使用智能指针,需要添加头文件 #include<memory>
3.内存四个区模型

内存分为四个区,分别是堆/栈/全区/代码起,
也有五个区的说法 栈/堆/全局/静态及常量/代码区
4.指针/引用

指针
        变量类型* 指针名 = 变量类型 变量
引用
        &别名 = 原名
两者的区别
指针是变量/引用是给变量起别名
指针可以为空/引用必须初始化
指针可以修改指向/引用不可改变
指针可以多级/引用只有一级
5.指针函数/函数指针

指针函数
        返回一个指针的函数
        int (*f)(int x,int y)
函数指针
        指向一个函数的指针
        int* sub (int x,int y)
6.构造函数

拷贝构造函数:

是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象
类自动生成的三个成员

当我们创建一个类的时候,会自动生成三个成员,分别是,默认构造函数(无参,函数体为空)、默认析构函数(无参,函数体为空)、默认拷贝构造函数,对属性进行值拷贝
构造函数的三种调用方式

构造函数的三种调用方式,括号法、显示法、隐式转换法
括号法
Person p1;
Person p2(10);
Person p3(p2);显示法
Person p1;
Person p2 = Person(10);
Person p3 = Person(p2);隐式转换法
Person p4 = 10;   //相当于 Person p4 = Person(10);
Person p5 = p4;深拷贝与浅拷贝

浅拷贝:简单的赋值拷贝操作,浅拷贝是编辑器自动生成的拷贝构造函数
深拷贝:在堆区重新申请空间,进行拷贝操作
浅拷贝存在问题:
        析构时堆区的内存重复释放
用深拷贝来解决
Person (const Person &p)
{
    m_age = p.m_age;
    m_Height = new int(*p.m_Height);
}7.静态成员

概念:所有对象共享同一份数据,类似游戏跨服的概念
静态成员变量:所有对象共享同一份数据,在编译阶段分配内存
类内生命类外初始化
static int age;
int person::age = 100;8.this

概念:this是一个指针,隐藏在每一个非静态成员函数中
两个常见用途:用来解决命名冲突、允许成员函数返回该对象
9.常函数

概念:被const修饰的函数
常函数内不可修改成员属性
可使用关键字mutable解除限制
常对象

声明对象前加const
常对象只能调用常函数
10.友元

全局函数做友元

把全局函数放到类里并添加friend关键字,全局函数即可访问私有成员
friend void ReadPublicAndPrivate(room* pRoom);类做友元

把访问类放到被访问类里并加friend关键字
friend class ClassName;成员函数做友元

告诉编辑器某个类下的某个函数可以访问我的私有成员
friend void 类名::函数名()11.运算符重载

概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型
关键字:operator
两种重载的方法:成员函数重载、全局函数重载
成员函数重载
Person operator+ (Person &p) //行参用指针或引用避免拷贝节省空间
{
        Person temp;
        temp.m_a = this->m_a+p.m_a;
        return temp
}

Person p3 = p1.operator+(p2);//本质调用
Person p3 = p1+p2;   //两种写法等同全局函数重载
Person operator+ (Person &p1,Person &p2)
{
        Person temp;
        temp.m_a = p1.m_a + p2.m_a;
        return temp;
}

Person p3 = operator+(p2,p1);//本质调用
Person p3 = p1+p2;   //两种写法等同12.继承

继承中的对象模型

父类中所有的非静态成员都会继承下来在子类中保存一份
包括私有变量,会被编辑器自动隐藏且不能访问
可使用 sizeof() 可以查看派生类大小
子类访问同名成员

默认访问子类自身成员
son.a;
son.fun();访问子类的父类方法
son.father::a;
son.father::fun();通过子类类名访问父类的静态成员
son::father::a;菱形继承

也叫钻石继承,会产生二义性,拥有两份数据,会造成资源浪费
我么可以利用虚继承 (virtual关键字) 来保证数据唯一
class son : virtual public father{};son为虚基类虚继承了father,son类会产生一个虚基类指针来保证数据唯一
13.多态

静态多态

地址早绑定,编译器编译时就知道调用哪个函数了比如函数重载运算符重载
动态多态

地址晚绑定,子类重写父类的虚函数,使用时利用父类的指针或引用来指向子类对象
虚函数

函数前加 virtual 关键字,自动生成虚函数指针(vfptr)并指向虚函数表(vftable)
子类重写虚函数时子类的虚函数表内部会替换成子类的虚函数地址
纯虚函数

语法:virtual 返回值类型 函数名(参数列表) = 0;
类中有了纯虚函数,这个类称为抽象类,抽象类无法实例化对象,
子类必须重写抽象类中的纯虚函数,否则也属于抽象类
虚析构和纯虚析构

虚析构:抽象类的析构函数前加 virtual关键字,可以解决父类指针释放子类对象时堆区数据释放不干净问题
纯虚析构函数:
virtual ~animal()=0;


animal::~animal()
{};14.文件操作

头文件<fstream>
文件类型分为两种 文本文件、二进制文件
操作文件的三大类: ofstream(写操作) ifstream(读操作)   fstream(读写操作)
5个步骤
包含头文件
#include<fstream>创建流对象
ofstream ofs;打开文件
ofs.open(“文件路径”,打开方式);

ios::in     //为读文件而打开文件
ios::out    //为写文件而打开文件
ios::ate    //初始位置:文件尾
ios::app    //追加方式写文件
ios::trunc  //如果文件存在先删除,在创建
ios::binary //二进制方式写数据
ofs<<"写入的数据";关闭文件
ofs.close();15.模版

函数模版

template<typename T>使用方法:
mySwap (5 , 4.9);   //自动类型推导
mySwap<int>(a,b);   //显示类型推模版函数与普通函数的区别
1.普通函数可以隐式类型转换
2.模版函数自动类型推导不可以隐式类型转换
3.模版函数显示指定类型可以发生隐式类型转
类模版

template<class T>        类模版只能用显示指定类型不能用自动类型推导
        类模版可以有默认参数
template<class NameType,class AgeType = int        实例化的对象向函数传参的方式:指定传入类型、参数模版化、整个类模版化
STL

六大组件:容器、算法、迭代器、仿函数、适配器、空间适配器
容器

容器分为序列式容器和关联式容器
常用的数据结构:数组/链表/树/栈/队列/集合/映射表
算法

质变算法:拷贝/替换/删除
非质变算法:查找/计数/遍历/寻找极值
迭代器

概念:迭代器式容器和算法之间的粘合剂,每个容器都有自己专属的迭代器,类似指针
16.智能指针

shared_ptr

共享指针,记录有多少指针指向了这块内存,当数量为0时自动释放
共享指针允许多个指针指向一块地址
头文件: #include<memory>声明和初始化语法
shared_ptr<int> p {new int(100)};
shared_ptr<int> p {make_shared<int>(100)};
Ball* rp = p.get();   //获取一个裸指针unique_ptr

独占指针,仅自己可以指向对应数据,用来指向唯一数据,数据是唯一的不可以copy
weak_ptr

是unique_ptr的补充
auto_ptr

已经被废弃

这是我梳理的关于C++的知识点,这也是进入虚幻引擎的必要条件,写到这里,代码也终于快编译完了。
这个专栏主要用来消磨编译时间的,还没想好后边写啥,可能会写点引擎源码方面的东西
发表于 2023-3-25 16:19 | 显示全部楼层
fantastic!
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-5-20 14:30 , Processed in 0.106887 second(s), 28 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表