1.可变参数

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
#include <iostream>
#include <stdarg.h> // 可变参数的支持
using namespace std;

// Java的可变参数: int ...
// C++的可变参数写法:...
// count的第一个用处:内部需要一个 存储地址用的参考值,如果没有第二个参数,内部他无法处理存放参数信息
// count主要还是用于记录可变参数个数,方便内部存取
void sum(int count, ...) {
va_list vp; // 可变参数的动作

// 参数一:可变参数开始的动作vp
// 参数二:内部需要一个 存储地址用的参考值,如果没有第二个参数,内部他无法处理存放参数信息
va_start(vp, count);

// 到这里后:vp就已经有丰富的信息

// 取出可变参数的一个值
int number = va_arg(vp, int);
cout << number << endl;

// 取出可变参数的一个值
number = va_arg(vp, int);
cout << number << endl;

// 取出可变参数的一个值
number = va_arg(vp, int);
cout << number << endl;

// 越界 系统值 乱码
// 取出可变参数的一个值 【取不到后,会取系统值 乱码】
number = va_arg(vp, int);
cout << number << endl;

// 关闭阶段
va_end(vp);
}

// 1.可变参数
int main() {
sum(3, 6,7,8);

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
// count变量的第二个用处,用于循环遍历长度
void sum(int count, ...) {
va_list vp; // 可变参数的动作

// 参数一:可变参数开始的动作vp
// 参数二:内部需要一个 存储地址用的参考值,如果没有第二个参数,内部他无法处理存放参数信息
va_start(vp, count);

// 到这里后:vp就已经有丰富的信息

for (int i = 0; i < count; ++i) {
int r = va_arg(vp, int);
cout << r << endl;
}

// 关闭阶段(规范:例如:file文件一样 要关闭)
va_end(vp);
}

// 1.可变参数
int main() {

sum(3, 6,7,8); // 真实开发过程的写法

return 0;
}

2.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
错误写法:不能在class中实现
class Dog {
public:
char * info;
int age;

// 已经编译不成功,不允许这样初始化
// static int id = 9;
static int id;

Dog() {
// 运行报错
// id = 9;
}

static void update() {
// 运行报错
// id = 9;
}

void update2() {
// 运行报错
// id = 9;
}
};

int main() {
Dog dog;
Dog::update(); // 类名::可以调用静态函数
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
44
正确写法:
/**
* 静态的总结:
* 1.可以直接通过类名::静态成员(字段/函数)
* 2.静态的属性必须要初始化,然后再实现(规则)
* 3.静态的函数只能取操作静态的属性和方法(Java)
*/

#include <iostream>

using namespace std;

class Dog {
public:
char * info;
int age;

// 先声明
static int id;

static void update() {
id += 100;

// 报错:静态函数不能调用非静态函数(Java)
// update2();
}

void update2() {
id = 13;
}
};

// 再实现
int Dog::id = 9;

int main() {
Dog dog;
dog.update2(); // 普通函数
Dog::update(); // 静态函数
dog.update(); // 对象名.静态函数(一般都是使用::调用静态成员,这种方式可以 知道就行)

cout << Dog::id << endl;
return 0;
}

3.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
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
// 3.C++对象中,为什么需要 this。
#include <iostream> // iostream.h 早期C++的方式
using namespace std;

class Student {
private:
char *name;
int age;

public:
static int id; // 先声明

public:
void setName(char *name) {
this->name = name;
}
void setAge(int age) {
this->age = age;
}
char *getName() {
return this->name;
}
int getAge() {
return this->age;
}

public:
// 默认的构造函数 栈区开辟空间 暴露 地址 == this指针 (和Java一致的思路)
};

// 再实现
int Student::id = 9527;

int main() {
// ======= 常规使用下而已
Student student;
student.setAge(99);
student.setName("Jack");
cout << student.getName() << " , " << student.getAge()<< endl;

// ========== this 纠结
Student student1;
student1.setAge(88); // 设置值的时候,它怎么知道是给student1的age设置值的?
student1.id = 880;

Student student2;
student2.setAge(99); // 设置值的时候,它怎么知道是给student2的age设置值的?
student2.id = 990;

Student::id = 666;

// 它怎么知道是获取student1的age
cout << " student1.getAge:" << student1.getAge() << endl;

// 它怎么知道是获取student2的age
cout << " student2.getAge:" << student2.getAge() << endl;

// 静态属性以最后设置为准
cout << "student1.id:" << student1.id << endl;
cout << "student2.id:" << student2.id << endl;
cout << "Student:::" << Student::id << endl;


return 0;
} // main函数弹栈会 隐士代码:(栈区:delete student ..., 堆区需要自己手动delete)

// 允许结果
Jack , 99
student1.getAge:88
student2.getAge:99
student1.id:666
student2.id:666
Student:::666

4.const修饰this

const没有修饰函数,this相当于指针常量,只能修改值,不能修改地址。

如果const修饰了函数,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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class Worker {
public:
char * name;
int age = NULL; // C++中不像Java,Java有默认值, 如果你不给默认值,那么就是系统值 -64664

// int * const 指针常量 指针常量【地址对应的值能改,地址不可以修改】
// const int * 常量指针 常量指针【地址可以修改,地址对应的值不能改】

// 纠结:原理:为什么可以修改age
// 默认持有隐士的this【类型 * const this】
// 类型 * const 指针常量:代表指针地址不能被修改,但是指针地址的值是可以修改的
void change1() {
// 代表指针地址不能被修改
// this = 0x6546; // 编译不通过,地址不能被修改,因为是指针常量
// 地址不可以修改
// this = 0x43563;

// 隐士的this
// 但是指针地址的值是可以修改的
// 地址对应的值能改
this->age = 100;
this->name = "JJJ";
}

// 默认现在:this 等价于 const Student * const 常量指针常量(地址不能改,地址对应的值不能改)
void changeAction() const {
// 地址不能改
// this = 0x43563;

// 地址对应的值不能改
// this->age = 100;
}

// 原理:修改隐士代码 const 类型 * const 常量指针常量
void showInfo() const {
// this->name = "";
// this->age = 88;

// 只读的
cout << "age:" << age << endl;
}
};

5.友元函数

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 <iostream>

using namespace std;

class Person {
private: // 私有的age,外界不能访问
int age = 0;

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

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

// 定义友元函数 (声明,没有实现)
friend void updateAge(Person * person, int age);
};

// 友元函数的实现,可以访问所以私有成员
void updateAge(Person* person, int age) {
// 默认情况下:不能修改 私有的age
// 通过友元函数可以修改私有成员,java反射是这样实现的么?
person->age = age;
}

int main() {
Person person = Person(9);
updateAge(&person, 88);

cout << person.getAge() << endl;
return 0;
}

4.友元类

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

class ImageView {
private:
int viewSize;
friend class Class; // 友元类
};

// Java每个类,都会有一个Class,此Class可以操作 ImageView私有成员
class Class {
public:
ImageView imageView;

void changeViewSize(int size) {
imageView.viewSize = size;
}

int getViewSize() {
return imageView.viewSize;
}
};

int main() {
Class mImageViewClass;

mImageViewClass.changeViewSize(600);

cout << mImageViewClass.getViewSize() << endl;

return 0;
}

5.各种定义和方法的区别

静态函数,友元函数,普通函数,构造函数,析构函数,拷贝构造函数,有什么区别。

头文件定义:

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

#ifndef PIG_H
#define PIG_H // 定义这个宏

class Pig {
private:
int age;
char * name;

public:
// 静态成员声明
static int id;

// 构造函数的声明系列
Pig();
Pig(char *);
Pig(char *,int);

// 析构函数
~Pig();

// 拷贝构造函数
Pig(const Pig & pig);

// 普通函数 set get
int getAge();
char * getName();
void setAge(int);
void setName(char *);

void showPigInfo() const; // 常量指针常量 只读

// 静态函数的声明
static void changeTag(int age);

// 不要这样干
// void changeTag(int age);

// 友元函数的声明
friend void changeAge(Pig * pig, int age);
};

#endif // 关闭/结尾

实现类

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

// TODO ====================== 下面是 普普通通 常规操作 对象::

// 实现构造函数
Pig::Pig() {
cout << "默认构造函数" << endl;
}

Pig::Pig(char * name) {
cout << "1个参数构造函数" << endl;
}

Pig::Pig(char * name, int age) {
cout << "2个参数构造函数" << endl;
}

// 实现析构函数
Pig::~Pig() {
cout << "析构函数" << endl;
}

// 实现 拷贝构造函数
Pig::Pig(const Pig &pig) {
cout << "拷贝构造函数" << endl;
}

int Pig::getAge() {
return this->age;
}
char * Pig::getName() {
return this->name;
}
void Pig::setAge(int age) {
this->age = age;
}
void Pig::setName(char * name) {
this->name = name;
}

void Pig::showPigInfo() const {

} // 常量指针常量 只读



// ===== 静态 和 友元 ==============

// 实现 静态属性【不需要增加 static关键字】
int Pig::id = 878;

// 实现静态函数,【不需要增加 static关键字】
void Pig::changeTag(int age) {

}

// 友元的实现
// 友元特殊:不需要关键字,也不需要 对象:: ,只需要保证 函数名(参数)
void changeAge(Pig * pig, int age) {

}