函数重载:必须改变参数列表才能实现函数重载,不能只改变返回类型
Class和Struct相像,区别为默认访问修饰符不一样:Class为Private,Struct为Public
构造函数和成员函数都可以在Class内部或外部定义(但需要在内部声明),在外部定义需要加上完全限制符(类名::)
在外部定义时,构造函数不指明返回类型(void),成员函数则需要指明返回类型,若不指明则默认为int
可以在构造函数里调用成员函数
在构造函数里初始化成员变量的另一种办法(相比于使用等号赋值语句)
Inheritance:类声明第一行后面加上
:public 父类名
父子类构造函数调用顺序和重载问题
不论有无输入参数,先调用父类默认(即不带输入参数的)构造函数,在调用本类对应输入参数的重载构造函数
如果使用以下语法(假设创建Dog实例时传入了下图三个参数)
则会调用父类对应参数的重载构造函数,而不调用无参数的构造函数
如果在Dog的构造函数体内调用了Animal构造函数(而不是使用冒号初始化列表),则先调用Animal的默认构造函数,再调用Dog的重载构造函数,再调用Animal的重载构造函数(并且最后调用的这个函数并不会影响到实际对象,而是创建了一个虚拟对象来操作),可以说是错误用法。
Private:仅限类内
Protected:仅限类内和派生类
Public:都行
关键字继承:(不写关键字则类默认private,结构体默认public)
例:class Dog : protected Animal {} ;
Animal类中所有public变量都变成protected,其余不变
Getter&Setter:变量设为private,而使用public的函数来对变量进行访问
栈上的内存自动管理,堆上的内存需要手动显式管理
new和delete关键字:在堆上分配和删除动态内存
NULL(0)和nullptr关系:
析构函数:~MyClass():释放类成员函数中动态分配的内存(等功能)
Static:
生命周期为全局
面向整个类,而非类的对象
静态类成员变量只能在类外部初始化
使用类名来调用静态成员函数MyClass::StaticFunction();,使用对象来调用非静态成员函数MyObject.NonStaticFunction();
对象可以访问静态变量,静态函数无法访问对象
初始化一次后就不能再初始化(初始化语句会被忽略)
如果定义在函数体内,则在函数体外部无法访问它(尽管其生命周期为全局)
Virtual:
非静态成员函数前加上virtual关键字
派生类即可重写(override)此函数,方法为(例)void Speak(){}(不用加virtual),并且此函数在派生类中依旧可以被重写(隐式标注了virtual)
为了可读性,可以在重写函数前加上virtual(代表此函数可以被重写),也可以在重写函数后加上override(代表此函数是基类一个函数的重写)
可以使用完全限定符来调用基类的被重写的原函数
Polymorphism
一个类实例的指针可以指向其所有子类的实例,并且调用继承函数时会调用相应的重写函数
Multi-Inheritance
使用“,”分隔开父类即可,每个父类前都要加关键字
对于菱形继承:
使用virtual关键字,确保只存在一个基类实例
Cast
dynamic_cast<目标类型>(源数据)
进行动态类型转换,类似UE::cast to
转换不安全则返回nullptr
需要基类有一个虚函数(支持多态)
static_cast<>()
静态类型转换,类似c语言的()强制类型转换
不会检查转换是否安全,需要自己判断
106B
强制类型转换
Headers
类声明写在.h文件里,定义写在.cpp文件里,名字一样,并且在.cpp文件开始时#include<文件名.h>即可
随后在main.cpp开头#include<>要用的头文件即可
#pragma once指令
防止一个头文件被多次包含(事实上,如果A包含了B,B包含了C,那么A就不用再包含C)