c++基础语法

c和c++联系

  1. c++代码可以混编c代码,既可以写c也可以调用c
  2. c++面向对象,c面向过程
  3. 开源框架大部分都是基于c++写的

打印

1
2
3
4
5
6
7
8
9
10
#include "stdio.h"
#include <iostream>

using namespace std;

void main() {
//打印
//cout << "hello world " << endl;//换行
cout << "hello world " ;//不换行
}

常量

1
2
3
4
5
6
7
8
9
void main() {
//常量
const int number = 0;
//在c文件,这里可以通过指针修改值,但是在c++中不能通过地址修改值,一般编译器编译不能通过,但是某一些编译器可以,但是也不能修改值
//int *number_p = &number;
//*number_p = 20;

getchar();
}

引用

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
#include "stdio.h"
#include <iostream>

using namespace std;

//通过指针来变换
void swap(int *num1,int* num2) {
int temp = 0;
temp = *num1;
*num1 = *num2;
*num2 = temp;
}

//通过引用来变换
void swap(int &num1, int& num2) {
cout << "number1p = " << &num1 << " number2p = " << &num2 << endl;//number1p = 00BBFA08 number2p = 00BBF9FC
int temp = 0;
temp = num1;
num1 =num2;
num2 = temp;
}

void main() {
//引用:四驱模型值的拷贝,引用其实是地址赋值,可以看成同一块内存的另外一个变量

//交换值
int number1 = 10;
int number2 = 20;
//通过指针
//swap(&number1,&number2);
//通过引用
cout << " number1p = " << &number1 << " number2p = " << &number2 <<endl; // number1p = 00BBFA08 number2p = 00BBF9FC
swap(number1,number2);

cout << "number1 = " << number1 << " number2 = " << number2 << endl;// number1 = 20 number2 = 10


//加深理解
int a = 10;
int b = a; //赋值 b 和 a分别指向不同的内存
cout << "ap = " << &a << " bp = " << &b << endl;// ap = 010FF730 bp = 010FF724

int& c = a;//引用 a和c都指向一块地址
cout << "ap = " << &a << " cp = " << &c << endl;// ap = 010FF730 cp = 010FF730
c = 20;
cout << "a = " << a << " c = " << c << endl;//a = 20 c = 20

getchar();
}

常量引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include "stdio.h"
#include <iostream>
#include <string.h>

using namespace std;

typedef struct
{
char name[20];
int age;
} Student;

//常量引用 const Student & stu只能读,不能修改
void insertStudent(/* const */ Student & stu) {
//stu.name = "李四"; //不能修改
strcpy_s(stu.name, "李四"); //这样的话就修改了值,如果不想修改stu,就在参数加上const 变为只读
}

void main() {
Student stu = {"张三" ,45};
insertStudent(stu);
cout << "stu.name = " << stu.name << " stu.age = " << stu.age << endl;
getchar();
}

重载 :c不支持重载 ,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
#include "stdio.h"
#include <iostream>
#include <string.h>

using namespace std;

//重载
//int add(int number1, int number2) {
//
// return number1 + number2;
//}

int add(int number1, int number2,bool cache = false) {

cout << cache << endl;

return number1 + number2;
}
int add(int number1, int number2,int number3) {

return number1 + number2 + number3;
}


void main() {
int number1 = 10;
int number2 = 20;
int number3 = 30;
int sum1 = add(number1, number2);
int sum2 = add(number1, number2 , number3);

printf("%d , %d", sum1, sum2);

getchar();
}

JAVA里的Class

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
#include "stdio.h"
#include <iostream>
#include <string.h>

using namespace std;

class Student{
private: // 私有 包装,影响下面所有的属性或者方法
char * name;
int age;

public://影响下面所有的方法或者属性

void setAge(int age){
this->age = age;
}
void setName(char*name) {
this->name = name;
}

int getAge() {
return this->age;
}

char * getName() {
return this->name;
}
};


void main() {
Student stu;
stu.setAge(25);
cout << stu.getAge() << endl;

Student *student = new Student();

student->setAge(24);

cout << student->getAge() << endl;

getchar();
}

注意:在开发过程中,cpp或者c会被编译为dll或者so供其调用者使用,一般把public的函数定义到h文件,不然调用者都不知道有哪些函数。

构造函数

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
class Student{

public:
//1.
Student() {};

//2.
Student(char * name):age(0) { // 相当于thix->age = 0
this->name = name;
};

//3.
//构造函数相互调用 先调用两个参数的,在调用一个参数的
Student(char*name) :Student(name,0) { // 相当于thix->age = 0
};

//4.
Student(char*name,int age) {
this->name = name;
this->age = age;
};

private:
char * name;
int age;

public:

void setAge(int age){
this->age = age;
}
void setName(char*name) {
this->name = name;
}

int getAge() {
return this->age;
}

char * getName() {
return this->name;
}
};

析构函数

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

class Student{

public:
Student() {};

Student(char*name,int age) {
this->name = (char*)malloc(sizeof(char)*100);
strcpy(this->name,name);
this->age = age;
};

//析构函数:对象被回收的时候会被调用,只能有一个,不能有参数
~Student() {
//释放内存 这里name使用malloc举个例子
free(this->name);
}


private:
char * name;
int age;

public:

void setAge(int age){
this->age = age;
}
void setName(char*name) {
this->name = name;
}

int getAge() {
return this->age;
}

char * getName() {
return this->name;
}
};

malloc free new delete区别

  1. malloc/free一起用 new/delete一起用
  2. malloc/free不会调用构造函数和析构函数,new/delete会调用构造函数和析构函数
  3. 如果用了new,一定要记得delete释放内存

拷贝构造函数

1
2
3
4
Class(const Class& C)  
{
//..赋值
}

https://blog.csdn.net/lwbeyond/article/details/6202256

可变参数 java的Object…

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

#include "stdio.h"
#include <stdarg.h>
#include <iostream>
using namespace std;

//可变参数
int sum(int count,...) {
va_list vp;
//可变参数指定开始 count代表从哪里开始
va_start(vp,count);
int sum = 0;
for (int i = 0; i < count; i++) {
sum += va_arg(vp, int);
}
va_end(vp);
return sum;
}

int main()
{

cout<<sum(3, 2, 3, 4)<<endl;
getchar();
return 0;
}

static

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
#include "stdio.h"
#include <stdarg.h>
#include <iostream>
using namespace std;

class Student
{
public:
char * name;
int age;
static int tag;


Student() {
tag = 10;
}

static void change() {
tag += 20;
}

void change2() {
tag += 20;
}

};


//静态属性 在c++中必须初始化,初始化必须这么写
int Student::tag =15;

int main()
{
cout << Student::tag << endl;//15

Student stu;
cout << Student::tag << endl;//10

Student::change(); //静态函数调用静态变量
cout << Student::tag << endl;//30

stu.change2(); //非静态函数调用静态变量
cout << Student::tag << endl;//50

getchar();
return 0;
}
// 1. 调用使用 双冒号 ::
// 2. 静态属性 必须初始化
// 2. 静态函数只能操作静态的相关函数和属性

const函数

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

#include "stdio.h"
#include <stdarg.h>
#include <iostream>
using namespace std;

class C
{
public:
int age;
public:
const void change() {
this->age += 12;
}

//const 在()之后主要用来限制this关键字
void change2() const {
//this->age += 12; //不能对类的属性进行修改
}

C(int age) {
this->age = age;
}

};


int main()
{
C *c = new C(15);
c->change();
cout << c->age << endl;


getchar();
return 0;
}

友元函数

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
#include "stdio.h"
#include <stdarg.h>
#include <iostream>
using namespace std;

class Person
{
public:
Person(int age) {
this->age = age;
};

int getAge() {
return this->age;
}
//友元函数 申明之后,friend_change就可以调用私有属性
friend void friend_change(Person * person, int age);


private:
int age = 0;


};

void friend_change(Person * person, int age) {
//age private修饰,在类的内部才能访问私有函数。如果非要访问,就得用到友元函数
//如果该方法设置为友元函数,那么在外部可以访问其私有属性
person->age = age;
}





int main()
{
Person person = Person(24);
friend_change(&person,20);
cout << person.getAge() << endl;//20
getchar();
return 0;
}

构造函数,析构函数,拷贝构造函数,普通函数,静态函数,友元函数实现

Student.h

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
#include "stdafx.h"

class Student
{
private:
int age;
int time;

public:
//静态属性的申明
static int tag;

public:
//构造函数
Student();
Student(int age);
Student(int time, int age);

//析构函数
~Student();
//拷贝构造函数
Student(const Student &student );


public:
void setAge(int age);
void setTime(int time);

int getAge();
int getTime();

void print() const;
//静态函数
static void changeTag(int tag_replease);
//友元函数
friend void changeAge(Student* stu,int age);

};

实现类 Student.cpp

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
#include "stdafx.h"
#include "Student.h"
#include <iostream>


//实现类,不一定都要全部实现


//静态属性的申明
int Student::tag = 0;


//构造函数
Student::Student(){

};

Student::Student(int age):time(200) { //time默认赋值
this->age = age;
}

Student::Student(int age,int time) {
this->age = age;
this->time = time;
}

//析构函数
Student::~Student() {
//资源回收
}
//拷贝构造函数
Student::Student(const Student& student) {

}

//普通方法
void Student::setAge(int age) {
this->age = age;
}
void Student::setTime(int time) {
this->time = time;
}

int Student::getAge() {
return this->age;
}
int Student::getTime() {
return this->time;
}

// const函数
void Student::print() const {
//this->age = 20;//不能操作this
std::cout << this->age << " " << this->time << " "<< tag << std::endl;
}

//静态函数
void Student::changeTag(int tag_replease) {
tag = tag_replease;
}

//友元函数 不需要加 Student::
void changeAge(Student* stu, int age) {
stu->age = age;
}

demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "stdafx.h"
#include "Student.h"


void main() {
Student* stu = new Student(24, 1000);
//调用const函数
stu->print();

//调用静态函数
Student::changeTag(36);
stu->print();

//调用友元函数
changeAge(stu, 37);
stu->print();


delete(stu);

getchar();
}

友元类 :java的反射获取属性可以理解为就是有一个Class类的友元类

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
class ImageView {
public:
//申明Class是ImageView 的友元类
friend class Class;
private:
int age;
};

class Class{
public:
void changeAge(int age) {
//正常情况下这是不能直接用的,申明友元类就可以用了
aObj.age = age;
}

int getAge() {
//正常情况下这是不能直接用的,申明友元类就可以用了
return aObj.age;
}
private :
ImageView aObj;
};


void main() {
Class b;
b.changeAge(10);
std::cout << b.getAge() << std::endl; // 10
getchar();
}

操作运算符

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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177

#include <iostream>

using namespace std;


class Vector
{
public:
Vector(int x, int y){
this->x = x;
this->y = y;
}

Vector(const Vector &vector){
this->x = vector.x;
this->y = vector.y;
cout << "拷贝构造函数" << endl;
}
private:
int x;
int y;

public:
void setX(int x){
this->x = x;
}
void setY(int y){
this->y = y;
}

int getX(){
return this->x;
}
int getY(){
return this->y;
}

// 重载减号运算符
// 为什么要用引用,为了防止重复创建对象
// const 关键常量,为了防止去修改值
Vector operator - (const Vector &vector){
int x = this->x - vector.x;
int y = this->y - vector.y;
Vector res(x, y);
return res;// 不建议返回引用
}

// 自增减运算符
void operator ++ (){// ++X
this->x = this->x++;
this->y = this->y++;
}

void operator ++ (int){// X++
this->x = this->x++;
this->y = this->y++;
}

// 自减
// 输出运算符
friend ostream & operator << (ostream &_Ostr, const Vector &vector){
_Ostr << vector.x << "," << vector.y << endl;
return _Ostr;
}

// 条件运算符
bool operator == (const Vector &vector){
return (this->x == vector.x && this->y == vector.y);
}
};

// 定义在类的外面,一般来讲我们定义在类的里面
// 重载运算 + :operator +
Vector operator + (Vector vector1, const Vector vector2){
int x = vector1.getX() + vector2.getX();
int y = vector1.getY() + vector2.getY();
Vector vector(x,y);
return vector;
}

void main(){
Vector vector1(2, 3);
Vector vector2(2, 3);

// java 中 string + string

// char* str = "123" + "456";

// 重载运算符 +
// Vector vector = vector1 - vector2;

// Vector vector(1, 2);
// vector++;
// ++vector;

// cout << vector.getX() << " , " << vector.getY() << endl;
// cout << vector << vector;
bool isEqual = vector1 == vector2;
cout << isEqual << endl;

// 可以重载加其他对象 Person

getchar();
}



// 括号运算符
class Array
{
public:
Array(int size){
this->size = size;
this->array = (int*)malloc(sizeof(int)*size);
}
~Array(){
if (this->array){
free(this->array);
this->array = NULL;
}
}

Array(const Array& array){
this->size = array.size;
this->array = (int*)malloc(sizeof(int)*array.size);

// 值的赋值
for (int i = 0; i < array.size; i++)
{
this -> array[i] = array.array[i];
}
}

private:
int size;
int* array;

public:
void set(int index,int value){
array[index] = value;
}

int get(int index){
return this->array[index];
}

int getSize(){
return this->size;
}

// 操作符[]
int operator[](int index){
return this->array[index];
}
};

void printfArray(Array array){
for (int i = 0; i < array.getSize(); i++)
{
cout << array[i] << endl;
}
}

void main(){

Array *array = new Array(5);

array->set(0,0);
array->set(1, 1);
array->set(2, 2);

printfArray(*array);

delete(array);
getchar();
}

类的继承 : 类继承,构造函数调用顺序:先父类 -> 再子类 ,析构函数调用顺序 : 先子类 -> 再父类

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

// 初始化属性
class Person{
// 变量修饰符
public:// 本类中使用
// protected :子类中能使用 (默认)
// public :公开,任何地方都可以
char* name;
int age;

public:
Person(char* name, int age){
this->name = name;
this->age = age;
cout << "Person 构造函数" << endl;
}

public:
void print(){
cout << this->name << " , " << this->age << endl;
}
};


class Student : public Person
{
private:
char* courseName;
public:
// : Person(name,age) 调用构造函数初始化父类的属性
// 不光可以给父类初始化属性,还可以给本类的属性进行初始化,用 , 隔开即可
Student(char* name, int age, char* courseName) :Person(name, age), courseName(courseName){// 调用父类构造函数
cout << "Student 构造函数" << endl;
}

void print(){
cout << "courseName: " << courseName << endl;
}
};

class Teacher: public Person
{
public:
Teacher(char*name,int age):Person(name,age){

}
};

void main(){
Student stu("张三",24,"语文");
stu.print();
getchar();
}
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
#include <iostream>
using namespace std;

class Person {
protected:
char* name;
int age;
public:
Person(char* name, int age){
this->name = name;
this->age = age;
}
};

class Course
{
private:// java String
string name;
public:
Course(string name){
this->name = name;
}

public:
string _name(){
return this->name;
}
};


class Student : public Person
{
private:
Course course;
public:
Student(char* name, int age, string courseName) : Person(name, age), course(courseName){ // 初始化父类的属性
}

void print(){
cout << name << "," << age << "," << course._name().c_str() << endl;
}
};

多继承

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
#include <iostream>
using namespace std;

class Person{
private:
char * name;

public:
Person(char * name){
this->name = name;
}

char* _name(){
return this->name;
}
};

class Child
{
int age;
public:
Child(int age){
this->age = age;
}

int _age(){
return this->age;
}
};

// 多继承,在 java 里面是不允许多继承 , c++ 是可以的,但是你也不能有二义性(歧义)
class Student : public Person, public Child // 多继承 , 并没有实现(接口)
{
public:
Student(char* name,int age):Person(name),Child(age){

}
};

虚继承:解决二义性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class A{
public:
char* name;
};

class B : virtual public A{ // virtual 确保继承过来的相同属性或者函数,只存在一份拷贝

};

class C :virtual public A{

};

class D : public B ,public C
{

};

多态:c++里面分为动态多态(子父类 需要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
class Activity
{
public:
virtual void onCreate(){ // 支持多态,虚函数
cout << "Activity 中的 onCreate" << endl;
}
};

class MainActivity : public Activity
{
public:
void onCreate(){
cout << "MainActivity 中的 onCreate" << endl;
}
};

class WelcomeActivity : public Activity
{
public:
void onCreate(){
cout << "WelcomeActivity 中的 onCreate" << endl;
}
};

void startActivity(Activity* activity){
activity->onCreate();
}

void main(){
Activity *activity1 = new MainActivity();// 父类 = new 子类对象
Activity *activity2 = new WelcomeActivity();

// activity->onCreate();
// c++ 中的多态是怎样的,默认情况下不存在
// 父类指向子类的引用,重写 ,里氏替换原则
// 程序在编译期间并不知晓运行的状态(我需要运行那个函数),只要在真正运行的过程中才会去找需要运行的方法
startActivity(activity1);//如果Activity里面onCreate不加virtual,那么将会执行Activity的onCreate不会执行MainActivity的onCreate
startActivity(activity2);

// c++ 多态:动态多态(子父类),静态多态(函数的重载)(编译过程确定性的区别)

getchar();
}

抽象类,抽象函数

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
// java 中类似的 抽象类,接口 纯虚函数
class BaseActivity // 跟 java 中的抽象类一个概念
{
public:
void onCreate(){// 普通函数
initView();
initData();
}

// 子类必须要实现
virtual void initData() = 0;// 虚函数,没有实现的,类似于 java 中的抽象方法,如果子类不实现会报错

virtual void initView() = 0;

};

// 如果不实现父类的纯虚函数,那么 MainActivity 也会变成抽象类,抽象类不允许实例化
class MainActivity : public BaseActivity
{
public:
void initData(){
cout << "initData" << endl;
}

void initView(){
cout << "initView" << endl;
}
};

void main(){

BaseActivity *m_a = new MainActivity();

m_a->onCreate();

getchar();
}

接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

class ClickListener{// 所有的函数都是虚函数,那么就可以认为是接口
public:
virtual void click() = 0;
};

class ImageClickListener : public ClickListener
{
public :
void click(){
cout << "图片点击" << endl;
}
};

void main(){
// 函数指针的时候:回调可以用 指针函数作为回调,纯虚函数类进行回调(接口)
// ClickListener *listener = new ImageClickListener();

//直接调用
// listener->click();

getchar();
}

模板函数 : java 中的泛型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 模板函数的定义
template <typename T> T add(T number1, T number2){
return number1 + number2;
}

void main(){

int sum1 = add(1,2);

cout << sum1 << endl;

int sum2 = add(1.0, 2.0);

cout << sum2 << endl;

int sum3 = add(1.0f, 2.0f);

cout << sum3 << endl;

getchar();
}

模板类

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
template <typename T> class Callback{
public:
void onError(){

}

void onSucceed(T result){
cout << result << endl;
}
};

// 模板类继承 ,子类如果也是模板类
// 如果子类不是模板类
class HttpCallback : public Callback<int>{

};

template <class T>
class HttpCallback : public Callback<T>{

};

void main(){
HttpCallback<int> *callback = new HttpCallback<int>();

callback->onSucceed(12);

getchar();
}

如果开发中涉及到模板类,申明和实现要写在同一个类里面: hpp = h + cpp/c (编译)

例如:c++实现ArrayList

ArrayList.hpp

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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include <malloc.h>
//------------------类的定义-------------------//

template<class E>
class ArrayList {
public:
// 数组头指针
E *array = NULL;
// 数组长度
int len = 0;
// 数据大小
int index = 0;
public:
ArrayList();

ArrayList(int len);

~ArrayList();

ArrayList(const ArrayList &list);

public:
bool add(E e);

int size();

E get(int index);

E remove(int index);

private:
void ensureCapacityInternal(int i);

void grow(int capacity);
};

//------------------类的实现-------------------//
template<class E>
ArrayList<E>::ArrayList() {

}

template<class E>
ArrayList<E>::ArrayList(int len) {
if (len == 0) {
return;
}
this->len = len;
this->array = (E *) malloc(sizeof(E) * len);
}

template<class E>
ArrayList<E>::~ArrayList() {
if (this->array) {
free(this->array);
this->array = NULL;
}
}

template<class E>
ArrayList<E>::ArrayList(const ArrayList &list) {
this->index = list.index;
this->len = list.len;
// 深拷贝
this->array = (E *) malloc(sizeof(E) * len);
memcpy(this->array,list.array,sizeof(E) * len);
}

template<class E>
E ArrayList<E>::get(int index) {
return this->array[index];
}

template<class E>
int ArrayList<E>::size() {
return this->index;
}

template<class E>
E ArrayList<E>::remove(int index) {
E old_value = this->array[index];
// 计算出需要逻动的个数
int numMoved = this->index - index - 1;

// 从前面不断的逻动
for (int i = 0; i < numMoved; ++i) {
array[index + i] = array[index + i + 1];
}

this->index -= 1;
return old_value;
}

template<class E>
bool ArrayList<E>::add(E e) {
ensureCapacityInternal(index + 1);
this->array[index++] = e;
return true;
}

// 是否需要调整当前数组大小
template<class E>
void ArrayList<E>::ensureCapacityInternal(int minCapacity) {
// 当前数组是不是空,或者 len 是不是 0
if (this->array == NULL) {
minCapacity = 10;// 第一次初始化大小
}

// 判断要不要扩容
if (minCapacity - len > 0) {
grow(minCapacity);
}
}

// 扩容创建新的数组
template<class E>
void ArrayList<E>::grow(int capacity) {
// 计算新数组大小的长度
int new_len = len + (len >> 1);

if (capacity - new_len > 0) {
new_len = capacity;
}

// 创建新的数组
E *new_arr = (E *) malloc(sizeof(E) * new_len);

if (this->array) {
// 拷贝数据
memcpy(new_arr, array, sizeof(E) * index);
// 释放原来的内存
free(this->array);
}

array = new_arr;
len = new_len;
}

使用的时候引入ArrayList.hpp

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
#include "ArrayList.hpp"
#include <jni.h>
#include <string>
#include <android/log.h>

#include "ArrayList.hpp"

extern "C"
JNIEXPORT void
JNICALL
Java_com_zzw_demo_MainActivity_test(
JNIEnv *env,
jobject /* this */) {

ArrayList<int> *list = new ArrayList<int>();//

for (int i = 0; i < 100; ++i) {
list->add(i);
}

for (int i = 0; i < list->size(); ++i) {
__android_log_print(ANDROID_LOG_ERROR,"TAG","i = %d",list->get(i));
}

delete(list);
}

异常处理

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

class Exception
{
public:
string msg;

public:
Exception(string msg){
this->msg = msg;
}

public:
const char *what(){
return this->msg.c_str();
}

};

// 异常的处理
void main(){
// c++ 中有自己一套异常的体系,不要去强记
// 但是 c++ 可以抛任何数据类型 try{}catch(数据类型 变量名){}
// throw 抛异常

try{
int i = -1;

if (i == 0){
throw Exception("出异常了");
}

if (i< 0){
throw 12.5f;
}
}
catch (int number){
cout << "捕捉到异常" <<number << endl;
}
catch (Exception exception){
cout << "捕捉到异常:" << exception.what() << endl;
}
catch (...){
cout << "捕捉到其他异常:" << endl;
}

getchar();
}

字符串常见操作

创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void main(){

string str1 = "123";
string str2("123");
string str3(5, 'A');// 5 个 A = AAAAA
string *str4 = new string("123");

// cout << str1.c_str() <<endl;
// cout << str2.c_str() << endl;
// cout << str3.c_str() << endl;
// cout << str4->c_str() << endl;

// string 与 char* 相互之间转换 c_str()
// const char* c_str1 = str1.c_str();
// cout << c_str1 << endl;

// char* -> string
char* c_str = "张三";
string str(c_str);// 对象
cout << str.c_str() << endl;


getchar();
}

遍历

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
void main(){

string str("1234567");

// 1. 字符串的遍历
for (int i = 0; i < str.length(); i++)
{
cout << str[i] << endl;
}

// 迭代器遍历
for (string::iterator it = str.begin(); it < str.end(); it++)
{
cout << *it << endl;
}

try{
for (int i = 0; i < str.length()+2; i++)
{
cout << str.at(i) << endl;// 如果越界会抛异常
}

for (int i = 0; i < str.length()+2; i++)
{
cout << str[i] << endl;// 会导致程序宕机,AS里面是可以的
}
}
catch (...){
cout << "异常了" << endl;
}

getchar();
}

添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void main(){

// 添加
string str1 = "123";
string str2 = "456";

// str1 = str1 + str2;
// str1.append(str2);


cout << str1.c_str() << endl;

getchar();
}

删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void main(){

// 删除
string str1 = "123 abc 123 abc 123";

// str1.erase(0,3);// 第一个参数:从哪里开始 ; 第二个参数:删除几个(默认值,字符串的结尾)

// 迭代器删除 2 bc 123 abc 123 解释 第一次删除第一个位置1,变为23 abc.... ,第二次删除第二个位置3,变为2 abc.... ,第三次删除第三个位置a,就是2 bc ....
for (string::iterator it = str1.begin(); it<str1.begin()+3; it++)// 删除一个字后都会从头开始计算
{
str1.erase(it);
}

cout << str1.c_str() << endl;

getchar();
}

替换

1
2
3
4
5
6
7
8
9
10
11
12
void main(){

string str1 = "123 abc 123 abc 123";
// 第一个参数:从哪里开始
// 第二个参数:替换几个
// 第三个参数:替换成谁
str1.replace(0,6,"1234");

cout << str1.c_str() << endl;

getchar();
}

查找

1
2
3
4
5
6
7
8
9
10
11
12
13

void main(){

string str1 = "123 abc 123 abc 123";
// 查找谁,从哪里开始
// int position = str1.find("123",0);
// 从后面往前面查
int position = str1.rfind("123");

cout << position << endl;

getchar();
}

大小写转换

1
2
3
4
5
6
7
8
9
10
11
12
void main(){

string str1 = "AAA abc BBB abc 123";
// 转换成大写
// transform(str1.begin(), str1.end(), str1.begin(), toupper);

transform(str1.begin(), str1.end(), str1.begin(), tolower);

cout << str1.c_str() << endl;

getchar();
}

STL标准模板库 : 容器+迭代+算法

  • 思想:集合,迭代器,算法 进行分离

vector容器(数组)

https://zh.cppreference.com/w/cpp/container/vector

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
容量

向量大小: vec.size();
向量真实大小: vec.capacity();
向量判空: vec.empty();


修改

末尾添加元素: vec.push_back();
末尾删除元素: vec.pop_back();
任意位置插入元素: vec.insert();
任意位置删除元素: vec.erase();
清空向量元素: vec.clear();


迭代器
开始指针:vec.begin();
末尾指针:vec.end(); //指向最后一个元素的下一个位置
指向常量的末尾指针: vec.cend();


元素的访问
下标访问: vec[1]; //并不会检查是否越界
at方法访问: vec.at(1); //以上两者的区别就是at会检查是否越界,是则抛出out of range异常
访问第一个元素: vec.front();
访问最后一个元素: vec.back();

stack容器(链表,数组)
https://zh.cppreference.com/w/cpp/container/stack

queue容器(数组,链表)
https://zh.cppreference.com/w/cpp/container/queue

list容器(链表)
https://zh.cppreference.com/w/cpp/container/list

set容器(红黑树,元素不重复)
https://zh.cppreference.com/w/cpp/container/set

multiset容器(元素可重复)
https://zh.cppreference.com/w/cpp/container/multiset

map容器(key不能重复)
https://zh.cppreference.com/w/cpp/container/map

multimap容器(以key分组)
https://zh.cppreference.com/w/cpp/container/multimap

对象添加到容器需要注意的:

  1. java 中把对象添加到了集合,c++ 中会调用对象的拷贝构造函数,存进去的是另一个对象
  2. 在c++中将对象加入到容器,需要有默认的构造函数
  3. 析构函数也可能回调用多次,如果说在析构函数中释放内存,需要在拷贝构造函数中进行深拷贝

仿函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

class Compare{
// 重载了括号运算符
public:
void operator()(){
cout << "仿函数" << endl;
}
};

void compare1(){
cout << "普通函数" << endl;
}

// 函数对象(仿函数) 一元谓词,二元谓词
void main(){
Compare compare;

// 跟函数非常类似
compare();//打印“仿函数”
// 普通函数调用
compare1();

getchar();
}

谓词

一元谓词

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

// 一元谓词
void print(int number){
cout << number << endl;
}

// 仿函数 - 一元谓词 (能够记录状态)
class PrintObj
{
public:
int count = 0;
public:
void operator()(int number){
cout << number << endl;
count++;
}
};

// 回调函数和仿函数的区别
void main() {

set<int> set1;
set1.insert(1);
set1.insert(2);
set1.insert(3);
set1.insert(4);

// for_each 迭代器 ,非常重要的一点就是:仿函数如果要保存记录状态,要确保对象一致,可以用返回值
// for_each(set1.begin(),set1.end(),print);//会打印
PrintObj printObj;
//for_each(set1.begin(), set1.end(), printObj);
//cout << "个数:" << printObj.count << endl; //个数:0 ,要确保对象一致
printObj = for_each(set1.begin(), set1.end(), printObj);
cout << "个数:" << printObj.count << endl; //个数:4 ,对象一致

getchar();
}

二元谓词

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

#include <set>
#include <iostream>

using namespace std;

class CompareObj{
public:
int count = 0;
public:
bool operator()(const string str1, const string str2) {
return str1 > str2;
}
};

void main() {
// 二元谓词的仿函数
set<string, CompareObj> set1;
set1.insert("aaa");
set1.insert("aAa");
set1.insert("ccc");
set1.insert("ddd");
// 是否包含 aaa , 遍历比较 , 找方法
for (set<string>::iterator it = set1.begin(); it != set1.end(); it++)
{
cout << (*it).c_str() << endl;
}
//ddd ccc aaa aAa
getchar();
}

预定义函数对象(自定义重载 () 运算符),函数适配器

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
#include<iostream>
#include<vector>
#include<set>
#include<functional>
#include<algorithm>

using namespace std;


// 自定义重载 () 运算符
//预定义函数对象
void main(){
// c/c++ 提供了很多定义好的函数对象
// 常见的几个 less ,greater,plus,equal_to
plus<string> strAdd;
string str = strAdd("aaa","bbb");

// cout << str.c_str() << endl;

set<string, greater<string>> set1;
set1.insert("aaa");
set1.insert("bbb");
set1.insert("ccc");

// 判断是不是包含 aaa
// 怎么写仿函数,一定要确定好你的仿函数的参数
// bind2nd 函数适配器 , aaa 相当于 equal_to 中的 right
set<string, greater<string>>::iterator find_it = find_if(set1.begin(), set1.end(),bind2nd(equal_to<string>(),"aaa"));
if (find_it != set1.end()){
cout << "找到了" << (*find_it).c_str() << endl;
}
else
{
cout << "没有找到" << endl;
}

getchar();
}
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
#include<iostream>
#include<vector>
#include<set>
#include<functional>
#include<algorithm>

using namespace std;

class Equal
{
private:
int equal_number;
public:
Equal(int equal_number) {
this->equal_number = equal_number;
}
public:
bool operator()(const int& number) {
return number == equal_number;
}
};

void main() {
vector<int> vector1;
vector1.push_back(1);
vector1.push_back(2);
vector1.push_back(3);
vector1.push_back(2);
vector1.push_back(4);
vector1.push_back(2);

// 找集合中 等于 2 的个数
int count = count_if(vector1.begin(), vector1.end(), Equal(2));
cout << "count = " << count << endl;

// 预定义好的函数对象 + 函数适配器
count = count_if(vector1.begin(), vector1.end(), bind2nd(equal_to<int>(), 2));
cout << "count = " << count << endl;

getchar();
}
  • foreach,transform
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
#include<iostream>
#include<vector>
#include<set>
#include<functional>
#include<algorithm>

using namespace std;

void print(int number) {
cout << number << endl;
}

// 进行修改
int transform_print(int number) {
// cout << number << endl;
return number + 3;
}

// foreach,transform,find,find_if,count,count_if,megre,sort,random_shuffle,copy,replace
// 常用预定义算法 循环,增,删,改,
void main() {
vector<int> vector1;
vector1.push_back(1);
vector1.push_back(2);
vector1.push_back(3);
vector1.push_back(4);

//for_each循环
// for_each(vector1.begin(), vector1.end(),print); //1234
vector<int> vector2;
vector2.resize(vector1.size());

//变换和循环
transform(vector1.begin(), vector1.end(), vector2.begin(), transform_print);//4567

for_each(vector2.begin(), vector2.end(), print);

getchar();
}
  • find,find_if
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
#include<iostream>
#include<vector>
#include<set>
#include<functional>
#include<algorithm>

using namespace std;

void print(int number) {
cout << number << endl;
}

// 进行修改
int transform_print(int number) {
// cout << number << endl;
return number + 3;
}

// foreach,transform,find,find_if,count,count_if,megre,sort,random_shuffle,copy,replace
// 常用预定义算法 循环,增,删,改,
void main() {
vector<int> vector1;
vector1.push_back(1);
vector1.push_back(2);
vector1.push_back(3);
vector1.push_back(4);

vector<int>::iterator find_it = find(vector1.begin(), vector1.end(), 2);

if (find_it != vector1.end()){
cout << "包含" << endl;
}
else
{
cout << "不包含" << endl;
}

// 有没有大于2的,自定义函数对象,预定义函数对象+函数适配器,省略...
//findif() //上面有
getchar();
}
  • count,count_if
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

void main(){
vector<int> vector1;
vector1.push_back(1);
vector1.push_back(2);
vector1.push_back(3);
vector1.push_back(2);
vector1.push_back(4);

int number = count(vector1.begin(), vector1.end(), 2);

cout << "等于2的个数:" << number << endl;

number = count_if(vector1.begin(), vector1.end(), bind2nd(less<int>(), 2));

cout << "小于2的个数:" << number << endl;

number = count_if(vector1.begin(), vector1.end(), bind2nd(greater<int>(), 2));

cout << "大于2的个数:" << number << endl;

getchar();
}
  • megre: 两个有序数组进行合并 - 归并排序
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

using namespace std;


void print(int number) {
cout << number << endl;
}

// megre,sort,random_shuffle,copy,replace
void main() {

// 两个有序数组进行合并 - 归并排序
vector<int> vector1;
vector1.push_back(1);
vector1.push_back(2);
vector1.push_back(3);

vector<int> vector2;
vector1.push_back(4);
vector1.push_back(5);
vector1.push_back(6);

vector<int> vector3;
vector3.resize(6);
merge(vector1.begin(), vector1.end(), vector2.begin(), vector2.end(), vector3.begin());
for_each(vector3.begin(), vector3.end(), print);

getchar();
}
  • soft,random_shuffle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void print(int number) {
cout << number << endl;
}

// sort,random_shuffle
void main() {

vector<int> vector1;
vector1.push_back(1);
vector1.push_back(3);
vector1.push_back(2);
vector1.push_back(4);

sort(vector1.begin(), vector1.end(), less<int>());
for_each(vector1.begin(), vector1.end(), print);

cout << "循环结束" << endl;

// 打乱循序
random_shuffle(vector1.begin(), vector1.end());
for_each(vector1.begin(), vector1.end(), print);

getchar();
}
  • copy,replace
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

void print(int number) {
cout << number << endl;
}

//copy,replace
void main() {

vector<int> vector1;
vector1.push_back(1);
vector1.push_back(2);
vector1.push_back(3);
vector1.push_back(4);

vector<int> vector2;
vector2.resize(2);
copy(vector1.begin(), vector1.begin() + 2, vector2.begin());
for_each(vector2.begin(), vector2.end(), print);

replace(vector1.begin(), vector1.end(), 2, 22);
for_each(vector1.begin(), vector1.end(), print);

getchar();
}
-------------The End-------------