C++ 回顾

大二上c++的复习

写这个文档,也能打印出来考试用


一.零散语法

1.两种创建类动态数组的方式

创建类数组,第一种适用于无参构造的类

1
2
3
4
5
6
7
8
9
class Point{
Point(){}
void print(){}
};

Point *p=new Point[5];
for(int i = 0;i<5;i++){
p[i].print();
}

第二种适用于有参构造的类

1
2
3
4
5
6
7
8
9
10
11
12
class Point{
Point(int a,int b){}
void print(){}
};
//创建一个指针
Point *p[5];
//初始化每个数组
for (int i = 0;i<5;i++){
p[i] = new Point(i,i);
p[i]->print();
}

2.动态矩阵

1
2
3
4
5
6
7
8
9
10
11
int m,n;
cin>>m>>n;
//为指针开辟堆空间
int **arr=new int *[m]
for(int i=0;i<m,i++)[
arr[i]=new int[n] //为每行分配空间
]
//释放矩阵
for (int i = 0; i < row; i++)
delete[] arr[i];
delete[] arr;

3.密钥循环

1
2
3
//例如,密钥是abc,要一直循环这3个密钥
//ly是密钥长度,i是当前循环
int num=(int *q + i%ly);

例题:

例如明文是abcde,密钥是234,那么加密方法就是a对应密钥的2,也就是a偏移2位转化为c;明文b对应密钥的3,就是b偏移3位转化为e,同理c偏移4位转化为g。这时候密钥已经使用完,那么又重头开始使用。因此明文的d对应密钥的2,转化为f,
明文的e对应密钥的3转化为h。所以明文abcde,密钥234,经过加密后得到密文是cegfh。

如果字母偏移的位数超过26个字母范围,则循环偏移,例如字母z偏移2位,就是转化为b,同理字母x偏移5位就是转化为c

使用三个指针p、q、s分别指向明文、密钥和密文,然后使用指针p和q来访问每个位置的字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void change(char *p,int lw, char *q,int ly) {
int i = 0;
int j = 0;
for (i = 0; i < lw; i++) {
int num = int(*(p + i)) + (int(*q + i%ly) - '0');
if (num>'Z'&&num<'a'||num>'z')
{
cout << char(num-26);
}
else
{
cout << char(num);
}
}
cout << endl;
}

4.冒泡排序

第一趟找出最大的放在最后,第二趟找出第二大的放在倒数第二

1
2
3
4
5
6
7
8
9
10
11
for (i = 0; i<N - 1; i++) { //控制n-1趟冒泡
for (j = 0; j<N - 1 - i; j++)
{
if (a[j]>a[j + 1]) { //比较相邻的两元素
int tmp; //临时变量
tmp = a[j]; //交换
a[j] = a[j + 1];
a[j + 1] = tmp;
}
}
}

5.整数拆分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void split(int num){
int n = num ;
int count = 0; //位数
int temp,power;
while(num != 0) {//统计位数
num = num / 10;
count ++;
}
for(int i= 1;i <= count;i++) {//提取n的各位
power = pow(10.0,count - i); //幂函数
temp = n / power;
cout<<temp<<endl;
n = n % power;
}
}

6.结构体

1
2
3
struct student{
int a,b,c;
};

二.类与对象

1.几种构造函数的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class ksjy{
private:
int c,int d;
public:
ksjy();//无参构造
ksjy(int a,int b){
c=a;
d=b;
};//有参构造
ksjy(int a=0,int b=0):c(a),d(b){}
};

//析构函数
Number::~Number(){
cout<<number<<" destructed."<<endl;}
for(i=2; i>=0;i--)
delete p[i];

在类外

1
2
ksjy::ksjy(){}
void ksjy::play(){}

2.拷贝构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Line
{
public:
int getLength( void );
Line( int len ); // 简单的构函数
Line( const Line &obj); // 拷贝构造函数
~Line(); // 析构函数
private:
int *ptr;
};
Line::Line(const Line &obj)
{
cout << "调用拷贝构造函数并为指针 ptr 分配内存" << endl;
ptr = new int;
*ptr = *obj.ptr; // 拷贝值
}
//main函数中调用
Line m(1);
line n(m);

3.静态数据成员和友元函数

静态数据成员:必须在类外定义和初始化

  • 被类的所有对象共享,包括派生类
  • 可以作为成员函数的可选参数,普通的不行
  • 类型可以是所属类的类型,普通数据成员则不行,只能用指针或者引用
  • 可以用对象名访问也可以用类名访问
1
2
3
4
class point{
static int count;
};
int point::count = 0;

静态成员函数:类外代码可以用类名和作用域来调用
只能引用属于该类的静态数据成员或者静态成员函数

1
2
3
4
5
6
7
8
9
10
class point{
static void showcount(){
cout<<count<<endl;
}
}
int main(){
point::showcount();
point a;
a.shoucount();
}

友元函数,在类外,可以访问类内对象,不是类内成员

1
2
3
4
class point(){
friend void ksjy(){}
}
void ksjy(){}

友元类,A将B声明为自己的友元,则B可以访问A的私有,但A不能访问B的

1
2
3
class a{
friend class b;
}

三.继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//基本语法
class abc: public y{};
//虚函数与多态
class BaseAccount{
virtual void speak(){}
}

int main(){
BaseAccount a1(a,b);
BaseAccount *p;
p=&a1;
p->speak();
}

//子类要构造函数,要加上基类
class BaseAccount{
BassAccount(int a,int b):name(a),account(b){}
}
class BasePlus: public Basesccount(){
BasePlus(int a,int b,string n,int m):BaseAccount(a,b),var(n),var2(m){}
}

虚继承 虚基类

多继承容易产生命名冲突

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class A{protected:int m_a;};
class B: public A{protected:int m_b;};//直接基类B
class C: public A{protected:int m_c;};//直接基类C
class D: public B, public C{//派生类D
public:
void seta(int a){ m_a = a; } //命名冲突
void setb(int b){ m_b = b; } //正确
void setc(int c){ m_c = c; } //正确
void setd(int d){ m_d = d; } //正确
private:
int m_d;
};
//所以用这种语法实现虚继承
class B:virtual public A{}
class C:virtual public A{}
class D:public B,public C{}

运算符重载

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
class Weight{ //抽象类
protected:
char kind[20]; //计重类型
int gram; //克
public:
Weight (char tk[]="no name", int tg=0)
{ strcpy(kind, tk);
gram = tg;
}
virtual void Print(ostream & out) = 0; //输出不同类型的计重信息
};
class CN: public Weight { //中国计重
//....类定义自行编写
protected:
int a,b,c;
public:
CN(int _a,int _b,int _c,int g,char _d[]):a(_a),b(_b),c(_c),Weight(_d,g){}
void Convert(int t){
gram=t;
a=gram/500;
b=gram%500/50;
c=gram%500%50/5;
gram=gram%500%50%5;
// cout<<a<<" "<<b<<" "<<c<<" "<<" "<<gram<<endl;
}
virtual void Print(ostream & out){
out<<"中国计重:"<<a<<"斤"<<b<<"两"<<c<<"钱"<<gram<<"克"<<endl;
}
CN &operator=(EN &e);
};
ostream & operator<<( ostream & out,Weight & w){
w.Print(out);
return out;
}
class EN: public Weight { //英国计重
//....类定义自行编写
protected:
int a,b,c;
public:
EN(int _a,int _b,int _c,int g,char _d[]):a(_a),b(_b),c(_c),Weight(_d,g){}
void Convert(int t){
gram=t;
a=gram/512;
b=gram%512/32;
c=gram%512%32/2;
gram=gram%512%32%2;
}
virtual void Print(ostream & out){
out<<"英国计重:"<<a<<"磅"<<b<<"盎司"<<c<<"打兰"<<gram<<"克"<<endl;
}
int getgram(){
return gram+a*512+b*32+c*2;
}
};
CN& CN::operator=(EN& e){
int all_g;
all_g=e.getgram();
this->Convert(all_g);
return *this;
}
//以全局函数方式重载输出运算符,代码3-5行....自行编写
//重载函数包含两个参数:ostream流对象、Weight类对象,参数可以是对象或对象引用
//重载函数必须调用参数Weight对象的Print方法
int main(){
int tw;
//创建一个中国计重类对象cn
//构造参数对应斤、两、钱、克、类型,其中克和类型是对应基类属性gram和kind
CN cn(0,0,0,0, "中国计重");
cin>>tw;
cn.Convert(tw); //把输入的克数转成中国计重
cout<<cn;
//创建英国计重类对象en
//构造参数对应磅、盎司、打兰、克、类型,其中克和类型是对应基类属性gram和kind
EN en(0,0,0,0,"英国计重");
cin>>tw;
en.Convert(tw); //把输入的克数转成英国计重
cout<<en;
cn=en; //把英国计重转成中国计重
cout<<cn;
return 0;
}

例2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//写在complex类内
friend Complex operator + (Complex &c1,Complex &c2);
friend Complex operator - (Complex &c1,Complex &c2);
friend Complex operator * (Complex &c1,Complex &c2);

//写在类外
Complex operator + (Complex &c1,Complex &c2){
Complex a;
a.Real=c1.Real+c2.Real;
a.Image=c1.Image+c2.Image;
return a;
}

//输出运算符重载
//类内
friend ostream & operator<<( ostream & os,const rmb & r);

ostream & operator<<( ostream & os,const rmb & r){
os<<"yuan="<<r.x<<" jiao="<<r.y<<" fen="<<r.z<<endl;
return os;
}

例3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//输入运算符
istream & operator>>(istream & in, complex & A){
in >> A.m_real >> A.m_imag;
return in;
}
//重载输出运算符
ostream & operator<<(ostream & out, complex & A){
out << A.m_real <<" + "<< A.m_imag <<" i ";;
return out;
}
int main(){
complex c1, c2, c3;
cin>>c1>>c2;
c3 = c1 + c2;
cout<<"c1 + c2 = "<<c3<<endl;
}
/*
输入输出
2.4 3.6↙
4.8 1.7↙
c1 + c2 = 7.2 + 5.3 i
*/

四.模版

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
输入
第一行先输入t,表示有t个测试用例
从第二行开始输入每个测试用例的数据。
首先输入数据类型,I表示int,D表示double,C表示char,接着输入两个参数m和n,分别表示矩阵的行和列
接下来输入矩阵的元素,一共m行,每行n个数据
输出转置后的矩阵
样例输入
2
I 2 3
1 2 3
4 5 6
C 3 3
a b c
d e f
g h i
样例输出
1 4
2 5
3 6
a d g
b e h
c f i
*/
#include <iostream>
using namespace std;
template<class type>
class matrix{
protected:
type **arr;
int m,n;
public:
matrix(int _m,int _n):m(_m),n(_n){}
void input(){
int i,j;
arr=new type*[m];
for(i=0;i<m;i++)
arr[i] = new type[n];
for(i=0;i<m;i++){
for(j=0;j<n;j++){
cin>>arr[i][j];
}
}
}
void transport(){
type **tem;
int i,j;
tem=new type*[n];
for(i=0;i<n;i++)
tem[i] = new type[m];
for(i=0;i<m;i++){
for(j=0;j<n;j++){
tem[j][i]=arr[i][j];
}
}
int c=0;
c=m;
m=n;
n=c;
arr=tem;

}
void print(){
int i,j;
for(i=0;i<m;i++){
for(j=0;j<n;j++){
cout<<arr[i][j]<<" ";
}
cout<<endl;
}
}
};

int main(){
int t;
cin>>t;
while(t--){
char c;
int m,n;
cin>>c;
cin>>m>>n;
switch (c){
case 'I':{
matrix<int> t1(m,n);
t1.input();
t1.transport();
t1.print();
break;
}
case 'D':{
matrix<double> t2(m,n);
t2.input();
t2.transport();
t2.print();
break;
}
case 'C':{
matrix<char> t3(m,n);
t3.input();
t3.transport();
t3.print();
break;

break;
}
}
}
return 0;
}

函数模板:

1
2
3
4
5
template<class T>
void a(T a[],int n){}
int main(){
a(b,c);//照常调用就行
}