摘要:面向对象
防卫式头文件
在头文件前后加
1
2
3
4
5
6
7
8
...
...
- ALGORITHM_COMPETITION_TRAINING_GUARD_H名字随便取
类
- 类分两种
- 一种带指针,大多是需要写析构函数的
- 一种不带指针,一般(九成以上)是不用在类内写析构函数的
构造函数
高级的写法
赋值时,使用列表参数
1
2
3
4
5
6
7
8
9class Complex {
private:
double re, im;
public:
Complex(double r = 0, double i = 0) : re(r), im(i) {
}
};上面写法等价于:
1
2
3
4Complex(double r = 0, double i = 0) {
re = r;
im = i;
}两者的区别是第一种更加高效。
重载
1
2
3
4
5
6
7
8
9class Complex {
private:
double re, im;
public:
Complex(double r, double i) : re(r), im(i) {
}
Complex() : re(0), im(0) {}//与上面冲突
};- 由于带参的构造函数是有默认参数的,所以
Complex() : re(0), im(0) {}
会发生冲突。因为如果类外定义了一个Complex c1;
那么它会去找构造函数,发现两个构造函数都可以,就不知道要哪一个,所以报错
- 由于带参的构造函数是有默认参数的,所以
构造函数如果放在私有里面,则外面是无法创建对象调用的
const
对于不改变函数里面的数据的,加上const,好习惯
1
2
3
4
5
6
7
8
9
10
11
12
13
14class Complex {
private:
double re, im;
public:
Complex(double r, double i) : re(r), im(i) {
}
double real() const{//不改变函数里面的数据
return re;
}
double imag() const {//不改变函数里面的数据
return im;
}
};- 比如在设计一个类时,有些方法是拿数据出来而不改变数据,就加上const
- 如果不加const,那么在类外用
const Complex complex(2, 1);
会报错
操作符重载
所有的成员函数都有this参数,只是没写出来
谁调用改成员函数,谁就是this
类外定义的,必定不用返回引用类型,因为函数调用已结束所有局部变量就消失了,所以返回的是值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19inline Complex operator + (const Complex &x, const Complex &y) {
return Complex(x.real() + y.real(), x.imag() + y.imag());
}
inline Complex operator+(const Complex &x, const double y) {
return Complex(x.real() + y, x.imag());
}
inline Complex operator+(const double x, const Complex &y) {
return Complex(y.real() + x, y.imag());
}
inline Complex operator+(const Complex &x) {
return x;
}
inline Complex operator-(const Complex &x) {
return Complex(-x.real(), -x.imag());
}如果返回引用类型,说明得到的结果会放在一个已经存在的变量里面,如下是this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29class Complex {
private:
double re, im;
public:
Complex(double r, double i) : re(r), im(i) {
}
Complex() {}
double real() const {
return re;
}
double imag() const {
return im;
}
double fun(const Complex &c) {
return c.re + c.im;
}
Complex& operator += (const Complex&);//声明
};
inline Complex& Complex::operator += (const Complex& complex) {
this->re += complex.re;
this->im += complex.im;
return *this;//返回引用类型
}
拷贝和析构
拷贝构造
构造函数的参数是该类的类型
拷贝赋值
如果类中有指针成员,那么一定要写拷贝构造和拷贝赋值,拷贝构造即深拷贝
不写的话是浅拷贝,会造成内存泄漏
1 | class MakeString { |
1 | //test MakeString |
1 | world |

堆栈
只要用到array new, 就一定要用array delete
Static
类内加了static的变量是所有类内成员函数共享的
静态函数和一般的成员函数的区别是:静态函数没有this指针
- 所以静态函数只能存取处理静态数据
定义了静态数据后,一定要在类外加一行,如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20class Account {
public:
static double rate;
static void set_rate(const double &x) {
rate = x;
}
};
double Account::rate = 5.0;
int main() {
Account account;
cout<<Account::rate<<endl;
account.set_rate(9);//Account::set_rate(9);
cout<<Account::rate<<endl;
return 0;
}1
2
3
45
9
Process finished with exit code 0- 静态变量可以通过对象或者类名调用
模板类
class template类模板
1 | template<typename T> |
function template函数模板
1 | //函数模板 |
namespace
标准库的所有东西都放在namespace std里面
1
2
3namespace std{
...
}三种使用方式
第一种最常用
1
2
3
4
5
6
7
8
using namespace std;
int main()
{
cin << ...;
cout << ...;
return 0;
}1
2
3
4
5
6
7
8
using std::cout;
int main()
{
std::cin << ...;
cout << ...;
return 0;
}1
2
3
4
5
6
7
8
int main()
{
std::cin << ;
std::cout << ...;
return 0;
}
几种关系
组合
一个类里面的数据类型是另一个类
1
2
3
4
5
6
7class B{
...
};
template<class T>
class A{
B <T> data;
};构造顺序是由内到外,如上是先调用B的构造函数,再A的
析构顺序是由外到内
委托
1 | class StringRep; |
然后把具体的实现放在StringRep类里面
继承
先调用父类的构造函数,再子类的(构造由内到外)
先定义子类的析构函数,再父类的(析构由外到内)
父类的析构函数必须是virtual的//养成良好的编程习惯
继承搭配虚函数使用更好
1
2
3
4
5
6
7
8
9class Shape {
public:
virtual void draw( ) const = 0;//纯虚函数后面带const = 0,一定要重写
virtual void error(const std::string& msg);//可以被重写
int objectID( ) const;//不可被重写
...
};
class Rectangle: public Shape { ... };
class Ellipse: public Shape { ... };- 如果是父类中想要子类被重写的函数,就加virtual
继承+组合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44class A {
public:
int age;
A(int age1) : age(age1) {
cout << "age birth is " << age << endl;
}
~A() {
cout << "over A class\n";
}
};
class Dad {
private:
string name;
public:
Dad(string str) : name(str) {
cout << "father is " << name << endl;
}
~Dad() {
cout << "over father\n";
}
};
class Son : public Dad {
private:
string name;
A age;
public:
Son(const string &str, const string &name1, const A &age1) : Dad(str), name(name1), age(age1) {
cout << "son is " << name << endl;
}
~Son() {
cout << "over son\n";
}
};
int main() {
Son("Nick", "Tom", 20);
return 0;
}1
2
3
4
5
6
7
8
9
10age birth is 20
father is Nick
son is Tom
over son
over A class
over father
over A class
Process finished with exit code 0- 调用构造函数的顺序是:先A类,再父类,再子类
- 析构的顺序与构造相反
STL基础
string
输入输出字符串
1 |
|
1 | 21314 hello woefsdcsd |
字符串拼凑
1 |
|
1 | shda sshda s5 |
排序
1 |
|
1 | 1122333455578 |
s.begin(), s.end()
是迭代器,可以看成是指针- 如果要访问最后一个字符,应该是
*(--s.end())
erase删除
1 |
|
1 | 52352543187 |
substr取子串
1 |
|
1 | 235 |
几种循环方式
1 |
|
1 | 1523525431873 |
vector
初始化、打印
1 |
|
1 | 111 |
取元素 []或者at()
1 |
|
追加push_back
1 |
|
1 | 12345777 |
resize重置大小,后面补0
1 |
|
1 | 12345777 |
erase删除,在vector中的复杂度为O(n)
1 |
|
1 | 12345777 |
front(),back()
1 |
|
1 | 12345777 |
排序sort
1 |
|
1 | 1 55 15 4 25 7 7 7 |
stack
初始化
- 一般刷算法题都直接这样写
stack<int> s;
- 如果不用
<bits/stdc++.h>
,那要用<stack>
1
2
3
4
5
6
7
using namespace std;
int main() {
stack<int> s;
cout << endl;
return 0;
}push, pop, top
1 |
|
1 | 31 |
1 |
|
1 | 1011 |
逆序输出句子单词
1 |
|
1 | we are young man |
字符串转化为数字
方法一
1 |
|
1 | 12455 |
方法二
1 | int main() { |
1 | 12455 |
数字转换为字符串
方法一
1 |
|
1 | 12556 |
方法二
1 |
|
1 | 12556 |
queue
1 |
|
1 | 3 4 |
map 和 unordered_map
- map: 有序的,底层是树状结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using namespace std;
int main() {
map<int, int> dict;
dict[1] = 2;
dict[2] = 0;
dict[4] = 12;
//打印
for (auto item: dict)
cout << item.first << ' ' << item.second << endl;
//另一种打印方式
for (auto iterator = dict.begin(); iterator != dict.end(); iterator++)
cout << iterator->first << ' ' << iterator->second << endl;
return 0;
}1
2
3
4
5
6
7
81 2
2 0
4 12
1 2
2 0
4 12
Process finished with exit code 0 - unordered——map:无序的,底层是哈希结构
1 |
|
1 | 4 12 |
1 |
|
1 | 232 |
deque
1 |
|
1 | 4312 |
可以排序
1 |
|
1 | 4312 |
list
1 |
|
1 | 3 2 4 1 |