面向过程
+ 三种循环
+ while(){}常用于不知道循环次数时,次数>=0,经常用法是while(1)、while(true),配合break使用;
+ for(;;){}常用于知道循环次数,次数>=0;
+ do{}while();至少做一次循环;
+ break和continue
+ break有两个用法
+ switch语句跳出case分支
+ 跳出本轮循环,后面循环都不做
+ continue一般用于跳出本次循环
+ 数组
+ 数组名是地址常量
+ 比如,int a[5]; int* p = a;
+ 数组不做初始化,里面是随机值。
+ int a[5];//{?,?,?,?,?}
+ 动态数组不能不指定动态开辟内存的个数。
+ int* a = new int[]{1,2,3,4,5};//错,先分配内存,再赋值
+ int* a = new int[5]{1,2,3,4,5};//对
+ int a[] = {1,2,3,4,5};//对,自动推导个数
+ 字符数组
+ char a[5];a = "xixi";//错,a依旧是字符常量
+ char a[5] = "12345"//错,越界
+ char a[5] = "1234"//对
+ char a[5] = {'1','2','3','4','\0'};//等价于第三种形式
+ 排序
+ 冒泡排序
```c++
const int N = 5;
int a[] = {5, 4, 3, 2, 1};
for (int i = 0; i < N - 1; i++) {
for (int j = 0; j < N - i - 1; j++) {
if (a[j] > a[j + 1]) {
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
```
+ 选择排序
```c++
const int N = 5;
int a[] = {5, 4, 3, 2, 1};
for (int i = 0; i < N - 1; i++) {
int k = i;
for (int j = i + 1; j < N; j++) {
if (a[j] < a[k]) {
k = j;
}
}
int temp = a[k];
a[k] = a[i];
a[i] = temp;
}
```
+ 指针
+ 指针:带类型的地址
+ int a;//&a
+ char c; //&c
+ 指针变量:用于存储`带类型的地址`的变量
+ int* pa = &a;
+ char* pc = &c;
+ *pa, *pc
+ 应用:
+ 动态开辟内存
+ int* a = new int[5];
+ int* a = new int(5);
+ 交换函数
```c++
void swap(int* a,int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int a = 5,b = 6;
swap(&a,&b);
return 0;
}
```
+ 多态
```c++
class Parent {
public:
virtual void show() {
cout << "这是基类show()方法";
}
};
class Son: public Parent {
public:
void show() {
cout << "这是子类show()方法";
}
};
void test() {
Parent *p = new Son;
p->show();
}
```
+ 全局变量和局部变量
+ 全局变量声明在函数外,声明处到文件结束可以被声明处后函数使用,会自动初始化
```c
void test0()
{
cout<<a;//错,不可见
}
int a;
void test1()
{
cout<<a;//0
}
void test2()
{
cout<<a;//0
}
```
+ 局部变量声明在函数内,声明处到函数结束可以被该函数使用,不初始化是随机值
+ 重载和重写
+ 重载:函数同名,参数类型、参数个数或参数顺序不同
```c++
//类型不同
void show(int a)
{
}
void show(float a)
{
}
```
```c++
//个数不同
void show()
{
}
void show(int a)
{
}
```
```c++
//顺序不同
void show(int a,float b)
{
}
void show(float b,int a)
{
}
```
```c++
//不是重载,重复定义函数,形参名不作为重载构成条件
void show(int a){}
void show(int b){}
```
+ 重写:针对基类虚方法,要求使用相同的名称和参数列表
```c
class Parent {
public:
virtual void show() {
cout << "这是基类show()方法";
}
};
class Son: public Parent {
public:
void show() {
cout << "这是子类show()方法";
}
};
void test() {
Parent *p = new Son;
p->show();
}
```
面向对象
+ 类
+ class和struct区别
+ class默认访问权限是private, struct默认访问权限是public
+ 构造函数和析构函数
+ 构造函数
```c
//1. 构造函数,没有返回值,也不写void
//2. 函数名称与类名相同
//3. 构造函数可以有参数,因此可以发生重载
//4. 程序在调用对象时候会自动调用构造,无须手动调用,而且只会调用一次
```
+ 析构函数
````c
//1. 析构函数,没有返回值,也不写void
//2. 函数名称与类名相同,在名称前加上符号~
//3. 析构函数不可以有参数,因此不可以发生重载
//4. 程序在对象销毁前会自动调用析构,无须手动调用,而且只会调用一次
````
````c++
class Person
{
public:
//构造函数
Person()
{
cout << "Person的构造函数调用" << endl;
}
//析构函数
~Person()
{
cout << "Person的析构函数调用" << endl;
}
};
````
+ 拷贝构造函数(类中存在指针成员再重写)
+ 重写的拷贝为深拷贝
+ 有指针成员不重写,导致浅拷贝,两个对象会对同一片内存空间进行析构两次
````c
class P
{
public:
P(const P& p) {
//1、开辟空间
l = p.l;
a = new int[l];
//2、赋值
for(int i=0;i<l;i++)
{
a[i] = (p.a)[i];
}
}
private:
int* a;//动态数组
int l;//长度
};
````
+ 三种构造函数的关系
````c
//如果用户定义有参构造函数,c++不再提供默认无参构造,但是会提供默认拷贝构造
// 如果用户定义拷贝构造函数,c++不会再提供其他构造函数
````
+ 静态成员变量和静态成员函数
+ 静态成员变量
```c
//所有对象共享同一份数据
//类内声明,类外初始化
//可通过类名访问,也可以通过对象访问
class Person {
public:
static int m_A; //静态成员变量
};
int Person::m_A = 10;
void test() {
//1、通过类名
cout << Person::m_A<<endl;
//2、通过对象
Person a;
cout << a.m_A<<endl;
}
```
+ 静态成员函数
```c
//所有对象共享同一个函数
//静态成员函数只能访问静态成员变量
//可通过类名访问,也可以通过对象访问
class Person
{
public:
static void func()
{
cout << "func调用" << endl;
m_A = 100;
//m_B = 100; //错误,不可以访问非静态成员变量
}
static int m_A; //静态成员变量
int m_B;
};
int Person::m_A = 10;
void test()
{
//1、通过对象
Person p1;
p1.func();
//2、通过类名
Person::func();
}
```
+ 友元
+ 友元的三种实现
+ 全局函数做友元
+ 类做友元
+ 成员函数做友元
````c
//全局函数做友元
class Building
{
friend void goodGay(Building * building);
private:
string m_SittingRoom; //客厅
string m_BedRoom; //卧室
};
void goodGay(Building * building)
{
cout << "好基友正在访问: " << building->m_SittingRoom << endl;
cout << "好基友正在访问: " << building->m_BedRoom << endl;
}
````
```c
//类做友元
class Building;
class goodGay
{
public:
goodGay();
void visit();
private:
Building *building;
};
class Building
{
friend class goodGay;
private:
string m_BedRoom;//卧室
string m_SittingRoom; //客厅
};
goodGay::goodGay()
{
building = new Building;
}
void goodGay::visit()
{
cout << "好基友正在访问" << building->m_SittingRoom << endl;
cout << "好基友正在访问" << building->m_BedRoom << endl;
}
```
```c
//成员函数做友元
class Building;
class goodGay
{
public:
goodGay();
void visit();
void visit2();
private:
Building *building;
};
class Building
{
friend void goodGay::visit();
public:
Building();
private:
string m_BedRoom;
string m_SittingRoom;
};
goodGay::goodGay()
{
building = new Building;
}
void goodGay::visit()
{
cout << "好基友正在访问" << building->m_SittingRoom << endl;
cout << "好基友正在访问" << building->m_BedRoom << endl;
}
void goodGay::visit2()
{
cout << "好基友正在访问" << building->m_SittingRoom << endl;//报错
cout << "好基友正在访问" << building->m_BedRoom << endl;//报错
}
```
+ 菱形继承
![clip_image002](E:\编程学习\C++\2、C++核心编程\讲义\assets\clip_image002.jpg)
````
//虚继承解决
class Animal
{
public:
int m_Age;
};
class Sheep : virtual public Animal {};
class Tuo : virtual public Animal {};
class SheepTuo : public Sheep, public Tuo {};
void test01()
{
SheepTuo st;
st.Sheep::m_Age = 100;
st.Tuo::m_Age = 200;
cout << "st.Sheep::m_Age = " << st.Sheep::m_Age << endl;
cout << "st.Tuo::m_Age = " << st.Tuo::m_Age << endl;
cout << "st.m_Age = " << st.m_Age << endl;
}
````
+ 虚函数和虚析构
+ 虚函数
+ 父类指针或引用指向子类时,想调用子类重写的方法,结果却是调用的父类的方法
```C
class Animal {
public:
virtual void Speak() = 0;
};
class Cat : public Animal {
public:
virtual void Speak()
{
cout << *m_Name << "小猫在说话!" << endl;
}
};
void test()
{
Animal* a = new Cat;
a -> Speak();
return 0;
}
```
+ 虚析构
+ 子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码
```c
class Animal {
public:
Animal()
{
cout << "Animal 构造函数调用!" << endl;
}
virtual ~Animal()
{
cout << "Animal虚析构函数调用!" << endl;
}
};
class Cat : public Animal {
public:
Cat(string name)
{
cout << "Cat构造函数调用!" << endl;
m_Name = new string(name);
}
~Cat()
{
cout << "Cat析构函数调用!" << endl;
if (this->m_Name != NULL) {
delete m_Name;
m_Name = NULL;
}
}
public:
string *m_Name;
};
void test01()
{
Animal *animal = new Cat("Tom");
animal->Speak();
}
```
+ 容器和迭代器
+ 常用容器:vector、list、set、map
+ vector
```c
void printVector(vector<int>& v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
void test()
{
//1、无参构造
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
//2、开辟10个空间,赋值为100
vector<int> v2(10, 100);
printVector(v2);
}
```
+ list
+ 和vector基本一致,常用多了个头插:push_front()
+ set
+ 不重复、会排序
```c
void printSet(set<int> & s)
{
for (set<int>::iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test()
{
set<int> s1;
s1.insert(40);
s1.insert(10);
s1.insert(30);
s1.insert(20);
printSet(s1);
}
```
+ map
+ map中所有元素都是pair,不允许重复key值,会根据键值排序
```c
void printMap(map<int,int>&m)
{
for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
{
cout << "key = " << it->first << " value = " << it->second << endl;
}
cout << endl;
}
void test01()
{
map<int,int>m;
//第一种插入方式
m.insert(pair<int, int>(1, 10));
//第二种插入方式
m[4] = 40;
printMap(m);
}