-
C++要点总结
- 注意缩进
- 补充类中未写完的方法
- 源码到 exe 的过程
- 数据类型与内存大小
- 函数的作用
- 头文件的使用
- 指针与引用
- 结构体与静态变量
- 枚举
- 构造器与析构函数
- 继承
- 接口
- 数组
- const 关键字
- 隐形转化
- this 指针
- 堆与栈
- 智能指针
- 模板
- 宏
- 后续遇到不懂再补充
c++要点:
要注意缩进,尤其是公共私有时
后续补充类中没写完的方法,在类外补充
源码到最后的exe,要经历编译和linker,
每个cpp文件都需要被转化成Obj文件,
preprocessing #include headfiles 全部抄过来
#define INTEGER
然后生成obj文件,然后通过linker连接在一起生成机器可读的二进制机器码。
int 4bytes 32bits
Unsighed 可以拓展到+2**32
唯一区别就是内存大小
char 1byte 单字符
short 2bytes
int
long
long long
Float 4
Double 8
Bool anyother number besides 0 is true 1byte
Sizeof(bool)算出byte数
函数是为了不让代码重复冗杂。
头文件中只需要声明函数,就可以在各个引用他的cpp文件里通用。当然这些引用的里包括了正式的定义。#include “Log.h”, #include<iostream> ””绝对路径与<>相对路径
Bool condition =ture;
For( ;condition; ){
Cout<<”ksjjakjs”<<endl;
I++;
If(!(i<5){
Condition=false;
}
}
raw :
pointers:一个指针就是一个地址(一个整数),不是类,所有指针都是一个地址
void* ptr 这样子ptr就是一个指针了且它的值就是一个地址,在所有现有的变量前加一个&就是在问这个变量的地址
*ptr代表ptr这个地址指向的值
reference:
引用不占用内存,只能引用已经存在的代码
int& 是一种类型
int a=5;
int& ref=a; 就像是给a取了一个别名,事实上a和ref一模一样,已经引用过的变量就不能再赋给别的变量了。(除非把ref换成指针类型)
结构体默认是公有的,plain old data可以用结构体装数据用的,没有什么方法有也是改变他的这些数据而已,别继承结构体,会很麻烦复杂。
static 静态变量,不会被linker总结至最后的exe,所以相当于类中的private,相当于私有了全局变量。
static在类中或者结构体中定义的变量,若使用实例改变这个值那么那个变量会改变,所有实例公用这些变量,静态方法没有实例可以引用,除非你给它传入一个实例,而非静态方法默认有一个实例传入。
枚举必须是整数,当有一组整数数据需要用到时可以考虑枚举
enum 名字{
};
构造器和类名同名,每个类自带一个构造器,构造器就是创建一个新对象并给他一些初始设置
class a{
a(){};//像这样
}
但是他什么都不会做
~类名(){} 析构函数:当对象被销毁时会自动调用
inheritance 继承
char* 4bytes
快捷的构造函数方法
player(const std::string& name):m_name(name){}
player(const std::string& name){
m_name=name;
}
如果想重写基类中的方法,需要将基类中的方法设置为虚拟
额外内存去存储v表
每次调用虚拟函数都需要通过这个表来确定实际映射到哪个函数
interface
接口类一般用来储存未实现的纯虚方法,虚拟写法,继承了接口就必须写完此方法,否则就无法实例化该类。
public private protected
private 在当类中可用
protected 在子类中可以用
public 在子类包括主函数中都可以调用
数组:
int example[5]; //默认为0
const是一个承诺,承诺之后就不能再改变,但是可读
int const* a=new int;
const int* a=new int;是一样的,只要const在星号前即可。说明指针不可修改
在星号和变量中间则说明变量不可被改变
int* const a;说明a指针指向的内容不可更改
写在类中方法后的const意味着这个方法不会修改实际类里的实体内容。(但是如果有mutable则可以)
int* my,mx;
只能把my设置成指针,但是还是一个int变量,除非在mx前加*
private:
string m_name;
public:
class():m_name(“ ”){};
if(s_level>5)
s_Speed=10;
else
s_Speed=5;
s_Speed=s_level>5?s_level>10?10:5:1; 否是后面的先输出
建立对象有两种方法:
- 在栈上建立 Entity entity;
- (对象太大,或者想显式的控制对象的生命周期)在堆(heap)上建立(must delete)
Entity* entity=new Entity();
delete entity;
new:在heap上生成
隐形转化只能转一次
explicit 当你只希望显式的调用构造函数而不是允许c++编译器隐式转换任何整数时
- 例如:一个类A的构造函数A(int i)就是,既可以用来作为构造器,又可以实现隐式转换A a=1;因为1可以通过构造函数A(int i)转换为一个类A的对象。(隐含的类型转换操作符)
this:
成员函数是类中的函数,this是指向对象的指针
Entity* entity=this;
比如我想将该实体类的当前实例传递到该函数中
void printEntity(Entity* e){}
class Entity{
Entity(){
printEntity(this);
}
}
堆 栈
不要在方法中创建数组等,因为当函数执行完栈中的东西就会被清除。要不就用new去堆中建立,或者使用智能指针。
智能指针:
可以不用delete,甚至不用new(heap堆)
特殊指针:
unique_ptr<Entity> entity=make_unique<Entity>();
entity->Print();
共享指针:
shared_ptr<Entity> sharedEntity=make_shared<Entity>();
shared_ptr<Entity> e0;
e0=sharedEntity;
一个变量赋给另一个变量,一个指针赋给另一个指针本质上都是copy过去,变量是copy过去内容他们两的地址不同,而指针是copy过去地址,而不是指针所指的实际内存
String(const String& other):m_Size(other.m_Size){
m_Buffer=new char[m_size+1];
memcpy(m_Buffer,other.m_Buffer,m_Size+1)
};
想传递对象打印,传值const Entity& entity
地址-> == 对象.
vector:
本质上是一个动态数组
没学懂的。。。
31 32 47 48 49 50 51 52 54 57 59 60 61
static 1.可以不让别的文件访问他,
- 可以在进程中更改
模板:
相同方法但是只是传值不一样,,编译器会根据函数实参来推断模板的具体类型,然后根据这个类型实例化这个类型的版本函数
template <typename T,int N>
class Array{
private:
T m_Array[N];
public:
int GetSize() const {return N;}
};
int main(){
Array<int,5> array;
cout<<array.GetSize()<<endl;
}
macro:编译前就会处理的信息
#define WAIT std::cin.get() //不要加分号
//下面的代码直接用WAIT,但这只是演示,but not a good way
auto:自动计算类型
(功能指针)function pointers:将函数分配给变量的一种方法
void HelloWorld(){};
int main(){
auto function=HelloWorld;
function();
//or
void(*cherno)()=Helloworld;
cherno();
//or
typeof void(*HelloWorldFuction)();
HelloWorldFunction function =HelloWorld;
function();
}
threads:线程被结束后,再建立线程会有新的id;
#include<thread>
void DoWork(){}
thread worker(DoWork);
github上c++高星知识总结,好用,推荐。