一、基础
#define 用在头部,表示一个常量。
const:将一个的变量转变为常量,不可修改。
const的用途
定义只读变量即常量
修饰函数的参数和函数的返回值
修饰函数的定义体,被const修饰表示不修改成员变量的值
变量名:1、不能是关键字。
只能是字母,数字,下划线。
只能是字母和下划线打头,数字不行。
short 2B int 4B long 4B longlong 8B
float 4B(要加f) double 8B
转义字符:\n 换行 == endl
\t 补齐8个位置 (水平制表) 补齐一个tab位
\\ == \
continue:执行到本行,就不再继续往下执行,会直接执行下次循环。
while:先判断在执行。 do while:先执行一次,在判断。
const int *p = &a;指针的指向可以改,但是指针指向的值不可以改。p = &b √ *p = 20 ×
int * const p = &a; 指针的指向不可以改,但是指针指向的值可以改。p = &b × *p = 20 √
p = 地址,*p = 值
值传递:若改变形参,实参不会改变。 地址传递:若在所调用函数中改变值,主函数中所对应的值也相应改变。
二、进阶
2.1四个区:代码区,全局区,栈区,堆区
![](https://img-blog.csdnimg.cn/img_convert/38528817e42dae2b791df536a9c10ff2.png)
程序运行前:
代码区:存放二进制的代码;共享,只读。
全局区:存放全局变量,静态变量(static),和全局常量。 局部变量和局部常量存放在其他地方。
程序运行后:
栈区:栈区的数据由编译器管理和释放。 用完了就直接释放
堆区:堆区的数据由程序员管理和释放,若程序员不是放,程序结束时由编译器释放。用完了不会自动释放 (new-delete)
new返回的是一个地址。
2.2、引用
10.引用:给变量起别名。 数据类型 &别名 = 原名
引用传参数时,形参改变,实参也会改变。
本质是 int * const p 指针常量
2.3、函数默认值
11.函数默认值
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//函数默认值
//1.如果某个位置参数有默认值,那么从这个参数,从左往右,都必须有默认值。
//2.函数声明和函数实现只能有一个有默认值。
int fun(int a, int b = 30, int c = 40) {
return a + b + c;
}
int main() {
int a = fun(10,10);
cout << a<< endl;
}
2.4 函数重载
12.函数重载满足条件:
同一个作用域下。
函数名相同。
函数参数的类型不同或个数不同,或顺序不同。
2.3函数封装
12.封装
#include <iostream>
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
#define PI 3.14
//class代表一个类,类+类名
/*
三种权限:
公共权限 public 成员类内可以访问,类外可以访问
保护权限 protected 成员类内可以访问,类外不可以访问(父亲可用,子也可用)
私有权限 private 成员类内可以访问,类外不可以访问(父亲可用,子不可用)
*/
class Circle {
//访问权限
public:
//类中的属性和行为都成为行为
//属性==成员属性或成员变量
//行为==成员函数或成员方法
//属性
int m_r;
//行为
double calcutateZC() {
return 2 * PI * m_r;
}
};
int main() {
//实例化(通过一个圆类创建一个对象)
Circle c1;
c1.m_r = 10;
cout << c1.calcutateZC() << endl;
}
struct和class的区别
class默认权限为private
struct默认权限为public
2.4构造函数和析构函数
13.
构造函数类名(){}
1.没有返回值也不写void
2.函数名和类名相同
3.有参数也可以重载
4.函数在调用对象时会自动调用构造,无需手动调用
析构函数 ~类名(){}
1.没有返回值也不写void
2.函数名称和类名相同,前面加~
3.没有参数,不可以重载
程序在销毁对象前会自动调用析构函数。
构造函数的分类和调用
按参数分类:无参构造(默认构造)和有参构造
按类型分类:普通构造 拷贝构造函数
调用:括号法,显示法,隐式转换法
![](https://img-blog.csdnimg.cn/img_convert/53bacf86e2927263aaa6c61c758f42d4.png)
2.5拷贝函数
![](https://img-blog.csdnimg.cn/img_convert/d1cf7f3df7d005954e53832167575665.png)
![](https://img-blog.csdnimg.cn/img_convert/3498d3fa49dcef8090600c1e71ed0549.png)
2.6浅拷贝和深拷贝
![](https://img-blog.csdnimg.cn/img_convert/5cfee2e5009eb0573e867e98c354c803.png)
2.7初始化列表
#include <iostream>
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
class person {
public:
int m_a;
int m_b;
int m_c;
//初始化
person(int a, int b, int c) :m_a(a), m_b(b), m_c(c) {
}
};
int main() {
person p(10, 50, 30);
cout << p.m_a<<endl;
cout << p.m_b << endl;
cout << p.m_c<<endl;
}
2.8成员对象
![](https://img-blog.csdnimg.cn/img_convert/b780c5a14b87501f4c44ce46c57de506.png)
2.9静态成员变量和静态成员函数
![](https://img-blog.csdnimg.cn/img_convert/caa950e66312dccd3037dd510d7bb740.png)
所有对象共享一份数据,当由成员改变数据的值时,其他成员所得到的数据也相应改变。
类外初始化 int person::m_a ::表示该类下的属性
类内定义,类外初始化
静态成员变量有访问权限:public,private,protected。
静态成员函数
![](https://img-blog.csdnimg.cn/img_convert/e6e5cf6262711c86d5a6b71b1a87bd67.png)
静态成员函数只能访问静态成员变量,不能访问非静态成员变量
静态成员函数有访问权限:public,private,protected。
2.10 成员变量和成员函数分开存储
只有非静态成员变量的地址是紧挨着类的起始地址存储的。
非静态成员变量是属于类的对象上的。
静态成员变量,非静态成员函数,静态成员函数都是不属于类的对象上的。
2.11 this指针
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class person{
public:
//this指针指向被调用的成员函数所属的对象
//this指针现在指向p1
person(int age) {
this->age = age;
}
//this是指向p2的指针,*this就是指向p2的本体
person& personAddAge(person &p) {
this->age += p.age;
return *this;
}
int age;
};
void test01() {
person p1(18);
cout << "p1的年龄为:" << p1.age << endl;
}
void test02() {
person p1(10);
person p2(10);
p2.personAddAge(p1).personAddAge(p1);
cout << "p1的年龄为:" << p2.age << endl;
}
int main() {
test01();
test02();
}
this指针的本质是指针常量,指针的指向是不可修改的,所指的值是可以修改的。
2.12 空指针访问成员函数
2.13 常函数和常对象
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class person {
public:
//加const之后,函数内成员变量的值不可修改
void showPerson() const {
//m_ageA = 100;
m_ageB = 100;
}
int m_ageA;
mutable int m_ageB;//加上mutable之后,常函数中的成员变量就可以修改了
};
int main() {
//常对象
//常对象只能调用常函数,不能调用普通的成员函数
const person p1;
p1.m_ageA = 100;
p1.m_ageB = 100;
}
2.14 友元 friend
可以访问私有的内容
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Building;
class Person {
public :
Person();
Building * building;
void visit1();
void visit2();
};
class Building {
//友元类
friend class Person;
//友元成员函数
friend void Person::visit2();
public:
Building();
string sittingRoom;
private:
string bedRoom;
};
Building::Building() {
sittingRoom = "客厅";
bedRoom = "卧室";
}
Person::Person() {
building = new Building;
}
void Person::visit1() {
cout << building->sittingRoom << endl;
//cout << building->bedRoom << endl;
}
void Person::visit2() {
cout << building->sittingRoom << endl;
cout << building->bedRoom << endl;
}
int main() {
Person p;
p.visit1();
}
2.15 继承
语法:class 子类 :继承方式 父类
子类:也称派生类
父类:也称基类
继承方式:公共继承,保护继承,私有继承
![](https://img-blog.csdnimg.cn/img_convert/0ac3a5ab2027e5812e8117ce86560a89.png)
![](https://img-blog.csdnimg.cn/img_convert/7086d8d100b74f4881715a555438abf5.png)
多继承: class 子类:继承方式 父类1,继承方式 父类2
2.16 多态
![](https://img-blog.csdnimg.cn/img_convert/bbb277ee38233738cef2565a93c8b809.png)
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
/*
动态多态:
1、有继承关系
2、子类重写父类函数
*/
class Animal {
public:
virtual void speak() { //虚函数
cout << "动物在说话" << endl;
}
};
class Cat :public Animal {
public:
//子函数重写父函数
//重写:函数返回值类型相同,函数名,函数列表完全相同
void speak() {
cout << "小猫在说话" << endl;
}
};
//运行时才确定函数的地址。
void doSpeak(Animal &animal) {
animal.speak();
}
int main() {
Cat cat;
doSpeak(cat);
}
当子类重写虚函数时,子类中的虚函数表内部会替换成子类的虚函数地址
当父类的指针或引用指向子类时,发生多态
Animal &animal = cat;
animal.speak();
2.17 纯虚函数和抽象类
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class base {
public:
//纯虚函数
//1.只要有一个纯虚数,这个类就成为抽象类
// 抽象类特点:
// 1、无法实例化对象
// 2、抽象类的子类,必须重写父类中的纯虚函数,否则也无法实例化对象
virtual void func() = 0;
};
class son:public base {
virtual void func() {
cout << "shixian" << endl;
}
};
void test01() {
//new的是谁,调用的就是那个函数
base* b = new son;
b->func();
}
int main() {
test01();
}
2.18 虚析构和纯虚析构
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class base {
public:
virtual void speak() = 0;
base() {
cout << "base 构造" << endl;
}
虚析构
//virtual ~base() {
// cout << "base 析构" << endl;
//}
//纯虚析构
//纯虚析构需要类内声明,类外实现
virtual ~base() = 0;
};
base::~base() {
cout << "base析构" << endl;
}
class cat :public base {
public:
cat(string name) {
cout << "cat构造" << endl;
m_name = new string (name);
}
void speak() {
cout << *m_name<<"小猫在说话" << endl;
}
~cat() {
if (m_name != NULL) {
cout << "cat构造函数" << endl;
delete m_name;
}
}
string *m_name;
};
int main() {
base *b = new cat("tom");
b->speak();
delete b;
}
2.19 写文件
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//1、包含头文件
#include<fstream>
void test() {
//2、创建流对象
ofstream ofs;
//3、指定路径和打开方式
ofs.open("test.txt",ios::out);
ofs << "123" << endl;
ofs.close();
}
int main() {
test();
}
三、提高
3.1模板
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
template<typename T>
void MYswap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}
int main() {
int a = 10;
int b = 20;
MYswap(a,b);
cout << a << " " << b << endl;
}
模板注意事项:
自动类型推导,必须推导出一致的数据类型T才可以使用
模板必须要确定出T的数据类型,才可以使用。
普通函数和模板的调用规则:
如果函数模板和普通函数都可以调用,优先调用普通函数
可以通过空模板参数列表的方式,强制调用函数模板
函数模板也可以重载
函数模板可以产生更好的匹配,优先调用函数模板
3.2类模板
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
template<class nameType,class ageType>
class person {
public:
person(nameType name, ageType age) {
m_name = name;
m_age = age;
}
void showPerson() {
cout << "姓名是:" << m_name << " 年龄是:" << m_age << endl;
}
nameType m_name;
ageType m_age;
};
void test() {
person<string,int>p1("bob", 18);
p1.showPerson();
}
int main() {
test();
}
类模板:没有推导参数
类模板在模板参数列表中可以有默认参数
四STL
4.1、string拼接字符串
![](https://img-blog.csdnimg.cn/img_convert/31ec5cab1e1ff28e3562925fbe673960.png)
4.2String查找和替换
![](https://img-blog.csdnimg.cn/img_convert/128bda470b5b24bdfeb1e1af524366d4.png)
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
void test01() {//查找和拼接
string str1 = "abcdefgfg";
int pos = str1.find("fg");//find有左往右找
cout << pos << endl;
int pos1 = str1.rfind("fg");//rfind从右往左找
cout << pos1 << endl;
}
void test02() {//替换
string str = "abcdefg";
//从1号位置起,3个字符,替换为"1111";
str.replace(1, 3, "1111");
cout << str << endl;
}
int main() {
//test01();
test02();
}
4.3、string字符串比较
按ASCII值比较
str1.compare(str2);
4.4、string字符存取
str[] 或者 str.at[]
4.5字串
substr(起始位置,字符个数)
4.5vector 数组(顺序表)
#define _CRT_SECURE_NO_WARNINGS
#include<vector>
#include<iostream>
using namespace std;
void printVector(vector<int>&v) {
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
void test() {
vector<int>v1;
//尾插法
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v1.push_back(40);
v1.push_back(50);
v1.push_back(60);
printVector(v1);
//插入
v1.insert(v1.begin(), 100);
printVector(v1);
v1.insert(v1.begin(),2, 1000);
printVector(v1);
//删除
v1.clear();
printVector(v1);
}
int main() {
test();
return 0;
}
![](https://img-blog.csdnimg.cn/img_convert/9511071d24298c9cdc3459285426fa08.png)
v.reserve() 预留空间
4.3deque容器(顺序表)
![](https://img-blog.csdnimg.cn/img_convert/7bdd6c2b21c48c9f9cf3b4db192b8751.png)
![](https://img-blog.csdnimg.cn/img_convert/7c2df9558fa051239beeebf3c72d88ba.png)
4.4 stack容器(栈)
![](https://img-blog.csdnimg.cn/img_convert/9a4a90aa17a8e2991385868f3968e08e.png)
4.5 queue容器(队列)
![](https://img-blog.csdnimg.cn/img_convert/47e847043cfd1215fcfb84ce23c4f2f6.png)
4.6list容器 (链表)
![](https://img-blog.csdnimg.cn/img_convert/71ad97eb849d145789641ffb75cdad52.png)
sort//排序
reverse//反转
4.7 set和multiset 容器 (二叉树和二叉排序树)
set不可以插入重复的数,multiset可以插入重复的数
插入数据使用 insert
set特点:
所有元素插入时自动排序
重复的数只会有一个
4.8队组
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
void test() {
pair<string, int> p = make_pair("Tom", 20);//两个值成对出现
cout << p.first << " " << p.second << endl;
}
int main() {
test();
}
4.9map和multimap
队组
4.10 算数仿函数
算数函数名<类型>对象名
例如:
plus<int> p;
p(10,20);
4.11. 关系仿函数
大于:greater
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;
void test() {
vector<int>v;
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
//关系仿函数 greater
sort(v.begin(), v.end(), greater<int>());
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}
}
int main() {
test();
}