1、pass by value / pass by pointer / pass by reference
pass by value:实参和形参不是同一个值,因此交换的是形参的值,当函数swap结束后,a和b的值并没有发生交换
pass by pointer and pass by reference :实参和形参是相同的。
2、动态内存
申请失败的返回值是 0 而不是 NULL, null在cpp中废止了。
申请一个长度我10,初始值都为0的空间
int *num= new int[10]();
3、对比new和malloc
4、cpp内存模型
内存模型:栈、堆、静态区、常量区。
5、数组内存模型
5、const char * / char * const / char const *
在c中,const是只读变量,cpp里const指的是常量。
6、常量指针和指针常量
下图为p1常量指针——p1所指地址上的内容不可以通过p1做出改动
下图p2为指针常量——p2所指的地址不可以发生改动
数组名就是一个指针常量
实例:
下图中的int const* pi和const int* pci是一样的
7、UML类图
一些编码规范:类名首字母大写;
8、匿名对象
9、访问对象成员
返回值类型 类名 : : 函数名
10、cpp的string类型
11、访问器与更改器
12、同名屏蔽
#include "pch.h"
#include<iostream>
using namespace std;
class Foo {
public:
int x;
int y;
Foo() {
x = 10;
y = 10;
}
void p() {
int x = 20;
cout << x << endl;
cout << y << endl;
}
};
int main(int argc, char **argv)
{
Foo foo;
foo.p();
return 0;
}
运行结果: 20 10
13、成员函数的this指针
14、避免同名屏蔽的简单方法
15、对象数组
#include "pch.h"
#include <iostream>
using namespace std;
class C {
public:
C(int i) { //带参构造函数
std::cout << "\t parameterized ctor" << std::endl;
}
C() { //无参(默认)构造函数
std::cout << "\t default ctor" << std::endl;
}
C(const C& c) { //拷贝构造函数
std::cout << "\t copy ctor" << std::endl;
}
C& operator =(const C& c) { //重载了类C的赋值运算符,观察main()中的对象赋值现象
std::cout << "\t assignment operator" << std::endl;
return *this;
}
};
int main() {
cout << "C c1;" << endl;
C c1; //调用无参(默认)构造函数
cout << "C c2(2);" << endl;
C c2(2); //调用有参构造函数
cout << "C c3 = c1;" << endl;
C c3 = c1; //调用拷贝构造函数
cout << "C c4 = C();" << endl;
C c4 = C(); //编译器将之等价为 C c4;
cout << "C c5 = C(5);" << endl;
C c5 = C(5); //编译器将之等价为 C c5(5);
cout << "C c6(c1);" << endl;
C c6(c1); //调用拷贝构造函数
cout << "C c7(C(7));" << endl;
C c7(C(7)); //编译器将之等价为 C c7(7);
cout << "C c8[4] = {C(), C(18), c7};" << endl;
C c8[4] = { C(), C(18), c7 }; //c8中的4个元素初始化时,是看做4个独立的对象处理:
//C c80 = C(); 调默认构造函数
//C c81 = C(18); 调有参构造函数
//C c82 = c7; 调拷贝构造函数
//C c83 = C(); 调默认构造函数
cout << "C c9; c9 = C(9);" << endl;
C c9; //调用默认构造函数
c9 = C(9); //先调用有参构造函数构造一个匿名对象C(9),然后调用赋值运算符将该匿名对象赋值给c9
return 0;
}
16、封装
当你的数据域是对象类型的时候,他必须放在构造函数的初始化列表里面进行构建,除非这个数据域的对象类型中有默认的无参构造函数。
17、不可变对象
定义:创建之后,不可变对象不可修改,除非通过成员拷贝。
如何让类“不可改变”:
1、数据域均设置为私有属性。
2、没有接口,使得外部可以调用来更改你的数据。
3、也没有能够返回可变数据域对象的引用或指针的访问器。
不可变类的一个特征是线程安全的,所以他有用。
18、避免多次声明
19、static
本文件内的static函数只允许本文件访问
下图中的静态数据成员numberofObjects,被类Circle的对象们共享。
静态成员变量只能放在所有函数的外面进行初始化
numberOfObjects一定要初始化,不然会报错
20、使用静态成员函数的规则
静态成员函数的访问规则
21、析构函数
22、拷贝构造
拷贝构造函数的形式以及何时会调用拷贝构造函数
注意下图右下角的赋值 x c = b; ,构造出的c里面传入的是默认参数 1 。
浅拷贝和深拷贝(类中数据成员如果含有指针,一定要自己写拷贝构造函数,因为编译器默认给生成的是浅拷贝版的拷贝构造函数,容易出问题的)
拷贝构造函数是一种特殊的构造函数
23、写一个类,实现栈的功能
24、写一个类,实现vector
24、一些编码规范
25、继承
派生类不能继承的是:
1、构造函数(cpp 11 中已经允许)
2、析构函数
3、友元函数
4、拷贝赋值函数
派生类构造函数调用基类构造函数的方法 :
若没有显示的调用基类的构造函数,则编译器默认调用无参的基类构造函数
(如果你写的构造函数有参,则编译器会报错,因为找不到无参的积累构造函数)
构造和析构的顺序
26、重定义
派生类对父类的同名函数内容进行修改。不修改的地方:
1、返回值类型
2、传入的参数
3、函数名
区分重定义和重载
27、绑定
基类中定义的虚函数,在派生类中的同名函数会自动变成虚函数,无需添加virtual关键字。
总结静态绑定和动态绑定
下面四张图的总结:
访问方式 | 访问对象 |
对象调用(p.f()) | 子类同名函数 |
父类指针指向子类对象(图2) | 父类同名函数 |
父类指针指向子类对象(图3) | 子类的同名虚函数 |
28、protected
protected成员可以被类内成员函数直接获取,不可以通过对象来获取。
29、几种继承方式的总结
30、抽象类与纯虚函数
抽象类(有纯虚函数的类是抽象类)不能被实例化
31、动态转换
32、向上转型和向下转型
向上转型可不使用dynamic_cast,而是隐式转换
向下转型必须使用dynamic_cast进行显示转换。
33、typeid运算符——用于获取对象所属的类的信息
可将派生类对象截取,只是用继承来的信息;但是不能将基类对象加长,无中生有变出派生类对象。(如下图:circle是派生类)