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
#include <iostream>
using namespace std; // 已经声明了

// 人类
class Person {
protected:
// 注意:string 是 std 命名空间里面的成员,C++源码是这种写法std::string
// string内部其实就是对 char*的封装
string name;
int age;
public:
Person(string name, int age) :name(name), age(age) {}
};

// 课程类
class Course {
private:
string name;
public:
Course(string name) :name(name) {}
};

class Student : public Person {
private:
// 如果定义的是对象成员,必须这样初始化(构造函数的后面 : 对象成员(内容)) 使用我们的第二种方式
Course course; // 对象成员
public:
Student(string name, int age, Course course1, string courseNameInfo)
:Person(name, age) // 既然继承了父类就必须给父类的构造函数初始化
// course(course1) // 第二种方式,编译阶段认可的 对象=对象 对象直接的赋值而已
,
course(courseNameInfo) // 第三种方式, 对象(string内容) 直接初始化Course对象 --- 构造函数
{
// this->course = course1; // 第一种方式(对象=对象) 编译阶段不认可,无法监测到你是否真的给course对象成员初始化了
}
};

int main() {
Course c("C++");
Student student("Jack", 30, c, "NDK内容真多");

return 0;
}

2. 多态

重写属于动态多态,重载属于静态多态。同一个方法有不同的实现。

2.1 动态多态

动态多态是只有在运行时才知道调用那个方法。

Java语言默认支持多态
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
44
45
46
47
48
49
50
51
52
53
54
55
#include <iostream>
using namespace std;

// Android标准
class BaseActivity {
public:
// 加上virtual关键字之后,C++就支持多态了
virtual void onStart() {
cout << "BaseActivity onStart" << endl;
}
};

class HomeActivity : public BaseActivity {
public:
void onStart() { // 重写父类的函数
cout << "HomeActivity onStart" << endl;
}
};

class LoginActivity : public BaseActivity {
public:
void onStart() { // 重写父类的函数
cout << "LoginActivity onStart" << endl;
}
};

// 在此函数 体现多态,例如:你传入HomeActivity,我就帮你运行HomeActivity
void startToActivity(BaseActivity * baseActivity) {
baseActivity->onStart();
}

int main() {
// TODO 第一个版本
HomeActivity *homeActivity = new HomeActivity();
LoginActivity *loginActivity = new LoginActivity();

// 如下调用输出BaseActivity的onstart()
// 因此C++默认不支持多态
startToActivity(homeActivity);
startToActivity(loginActivity);

if (homeActivity && loginActivity) delete homeActivity; delete loginActivity;


cout << endl;


// TODO 第二个版本
BaseActivity * activity1 = new HomeActivity();
BaseActivity * activity2 = new LoginActivity();
startToActivity(activity1);
startToActivity(activity2);

return 0;
}
2.2 静态多态

在编译器就确定调用某个方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
using namespace std;

void add(int number1, int number2) {
cout << number1 + number2 << endl;
}

void add(float number1, float number2) {
cout << number1 + number2 << endl;
}

void add(double number1, double number2) {
cout << number1 + number2 << endl;
}

int main() {
add(10000, 10000);
add(1.9f, 2.8f);
add(545.4, 654.54);

return 0;
}

3. 纯虚函数

总结:虚函数为了基类支持多态,解决C++二义性;存虚函数为了让子类实现。

在C++中不支持抽象类和接口的定义,所以就引出了纯虚函数和全纯虚函数。

纯虚函数相等于JAVA中的抽象类;全纯虚函数相当于JAVA中的接口。

纯虚函数定义最后要有 “= 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
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
// 纯虚函数
#include <iostream>
using namespace std;

// 抽象类/纯虚函数: 分为:1.普通函数, 2.抽象函数/纯虚函数
class BaseActivity {
private:
void setContentView(string layoutResID) {
cout << "XmlResourceParser解析布局文件信息... 反射" << endl;
}

public:
// 1.普通函数
void onCreate() {
setContentView(getLayoutID());

initView();
initData();
initListener();
}

// 纯虚函数是必须继承的(如果子类没有重写纯虚函数,子类就是抽象类), 虚函数是不是不必须的

// 2.抽象函数/纯虚函数
// virtual string getLayoutID(); // 虚函数
virtual string getLayoutID() = 0; // 纯虚函数
virtual void initView() = 0;
virtual void initData() = 0;
virtual void initListener() = 0;
};

// 子类 MainActivity
class MainActivity : public BaseActivity { // MainActivity如果没有重新父类的纯虚函数,自己就相当于抽象类了

string getLayoutID() {
return "R.layout.activity_main";
}

void initView() {
// Button btLogin = findViewById(R.id.bt_login);
// Button btRegister = findViewById(R.id.bt_register);
// TextView tvInfo = findViewById(R.id.tv_info);
// ... 省略
}

void initData() {
// tvInfo.setText("info...");
// ... 省略
}

void initListener() {
/*btLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 点击做事情
}
});*/
// ... 省略
}
};

int main() {

// 错误:抽象类型 MainActivity 绝对不能实例化
// MainActivity mainActivity;

// 重新了父类所有的纯虚函数
MainActivity mainActivity;

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
// 全纯虚函数
#include <iostream>
using namespace std;

class Student {
int _id;
string name;
int age;
};

// 此类所有的函数 ,都是纯虚函数,就相当于 Java的接口了
class ISudent_DB {
virtual void insertStudent(Student student) = 0;
virtual void deleteStudent(int _id) = 0;
virtual void updateStudent(int _id, Student student) = 0;
virtual Student queryByStudent(Student student) = 0;
};

// Java的实现类
class Student_DBImpl1 : public ISudent_DB {
public:
void insertStudent(Student student) {
// 插入操作,省略代码...
}

void deleteStudent(int _id) {
// 删除操作,省略代码...
}

void updateStudent(int _id, Student student) {
// 更新操作,省略代码...
}

Student queryByStudent(Student student) {
// 查询操作,省略代码...
}
};

int main() {
Student_DBImpl1 studentDbImpl1;

cout << "Success" << endl;
return 0;
}

4. 模板函数

C++中模板函数非常类似JAVA中泛型。

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

using namespace std;

// 加分合集 int double float ... 你都要考虑,你是不是要定义很多的 函数
/*void addAction(int n1, int n2) {
cout << "addAction(int n1, int n2):" << n1 + n1 << endl;
}

void addAction(float n1, float n2) {
cout << "addAction(int n1, int n2):" << n1 + n1 << endl;
}

void addAction(double n1, double n2) {
cout << "addAction(int n1, int n2):" << n1 + n1 << endl;
}*/

// 模板函数 == Java的泛型解决此问题
template <typename TT>
void addAction(TT n1, TT n2) {
cout << "模板函数:" << n1 + n2 << endl;
}

int main() {
addAction(1, 2);
addAction(10.2f, 20.3f);
addAction(545.34, 324.3);
addAction<string>("AAA", "BBB");

// 因为是一个TT,类型必须要统一
/*addAction(2, 324.3);
addAction(54, 324.3f);*/
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
46
#include <iostream>

using namespace std;

class Person {
public:
string name;

Person(string name) : name(name) {cout << "Person构造函数" << endl;}

~Person() {cout << "Person析构函数" << endl;}

virtual void test() {
cout << "父 test..." << endl;
}
};

class Student : public Person {
public:
string name;

Student(string name) : Person(name) {
cout << "Student构造函数" << endl;

// Person::test();
}

~Student() {cout << "Student析构函数" << endl;}

void test() {
cout << "子 test..." << endl;
}
};

int main() {
Student student("Jack");
// Person构造函数
// Student构造函数
// Student析构函数
// Person析构函数

Student student1("A");
student1.test(); //调用的子类

return 0;
}