C++面向对象基础

2

C++面向对象基础

  面向对象的编程思想(Object Oriented Programming, OOP)是程序设计发展的必然阶段,在70年代初,人们使用面向过程的编程思想解决问题,但是随着时代的进步,人们发现这种编程思想非常繁琐,尤其是定义多个相同或相似的变量,需要进行非常冗余的代码编写。这就引入了OOP的观念,面向对象的思想是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
#include<iostream>
using namespace std;

//定义类时,需要使用class关键字 + 类名,然后在花括号中定义成员变量和成员方法。
//是不是和结构体非常类似,最简单的类和结构体非常类似,但是类具有结构体所没有的特殊性质,在后面会一一为大家介绍。
//这种将成员变量和成员方法写在一个类中,创建对象时,所有对象都具有这些成员变量,也可以使用成员方法,这种思想称为封装。
class Person {

public:
string name;
int age;

void eat() {

cout << "I am hungry!" << endl;
}

void sleep() {

cout << "I am sleepy!" << endl;
}
};


int main() {

//对象的创建,可以通过类名 变量名(参数列表)进行创建,但是如果没有参数则不能加括号,否则会和函数的声明发生冲突。
Person p1;

//对象的使用,如果想访问对象的成员变量或者成员方法和结构体相同,使用小数点进行访问。
p1.name = "睡神";
p1.age = 24;

cout << "我的名字是:" << p1.name << endl;
cout << "我的年龄是:" << p1.age << endl;
p1.eat();
p1.sleep();

return 0;
}

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
45
46
47
48
49
#include<iostream>
using namespace std;

class Person {
public:
string name="xxx";
int age = 0;

//构造函数是和类名同名的一种特殊的成员函数,当创建对象时会自动调用类的构造函数。
//如果没有自定义构造函数,编译器会自动帮你创建一个无参的构造函数,里面是空实现。
Person(string name, int age) {
this->name = name;
this->age = age;
cout << "我是" << this->name << "我有两个参数的构造函数,我被执行了~" << endl;
}

//构造函数的出现帮我们省去了每个成员变量重新赋值的操作,而且构造函数可以发生函数重载。
//注意构造函数的写法,没有返回值。
Person(string name) {
this->name = name;
cout << "我是" << this->name << "我有一个参数的构造函数,我被执行了~" << endl;
}

Person() {
cout << "我是" << this->name << "无参的构造函数,我被执行了~" << endl;
}

//析构函数和构造函数相反,是在类名前加一个波浪号,没有返回值,析构函数是在对象销毁时调用,因此没有参数,也不可以发生重载。
~Person() {
cout << "我是" << this->name <<"的析构函数,我被执行了~" << endl;
}
};


int main() {

//在一个花括号种写代码,则花括号为代码的作用域,当执行结束后,会销毁其中的变量,所以在执行结束后会自动调用对象的析构函数。
{
Person p1;
Person p2("婴儿");
Person p3("程序员", 24);

cout << p1.name << "的年龄是:" << p1.age << endl;
cout << p2.name << "的年龄是:" << p2.age << endl;
cout << p3.name << "的年龄是:" << p3.age << endl;
}

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
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="xxx";
int age = 0;

//拷贝构造函数的参数是一个同类型的对象,可以根据传入的对象创建一个相同的对象,为了防止对传入对象的误操作,可以在前面加const关键字修饰。
//默认情况下编译器会提供一个默认无参构造函数,一个默认拷贝构造函数和一个默认析构函数。
//如果程序员自定义了一个构造函数,则编译器不会提供默认的无参构造函数,但是会提供拷贝构造函数和析构函数。
//如果程序员自定义了一个拷贝构造函数,则编译器不会再提供任何构造函数,只会提供析构函数。
Person(const Person& p) {
this->name = p.name;
this->age = p.age;
cout << "我是" << this->name << "的拷贝构造函数,我被执行了~" << endl;
}

Person(string name, int age) {
this->name = name;
this->age = age;
cout << "我是" << this->name << "我有两个参数的构造函数,我被执行了~" << endl;
}

~Person() {
cout << "我是" << this->name <<"的析构函数,我被执行了~" << endl;
}
};


int main() {

{
Person p1("程序员", 24);
//使用p1对象拷贝构造一个p2对象,具有和p1对象相同的成员变量,但是两个对象,具有不同的地址值。
Person p2(p1);

cout << p1.name << "的年龄是:" << p1.age << endl;
cout << p2.name << "的年龄是:" << p2.age << endl;

cout << "p1的地址是:" << &p1 << endl;
cout << "p2的地址是:" << &p2 << endl;
}

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

class Person {
public:
string name = "xxx";
int age = 0;
int* p = NULL;

//在构造函数中申请了一段内存,并且在析构函数中完成释放。
//此时如果使用默认的拷贝构造函数,则新创建的对象是浅拷贝第一个对象,此时两个对象创建的内存是同一块内存。
//这时在释放内存时,第一次释放成功,第二次释放就会失败,并且产生异常。
//解决方法是重写拷贝构造函数,并且在构造函数中重新申请内存。
Person(const Person& p) {
this->name = p.name;
this->age = p.age;
this->p = new int(10);
cout << "我是" << this->name << "的拷贝构造函数,我被执行了~" << endl;
}

//深拷贝:指当对象或者变量复制时,不是简单的赋值操作,而是内存的重新分配,即两个对象或者变量中的地址是不重复的。修改了原对象,拷贝构造对象不会发生改变。
//浅拷贝:指当对象或者变量复制时,通过简单的赋值号,完成拷贝,两个对象或者变量可能指向同一块内存地址。修改了原对象,拷贝构造对象也会发生改变。
Person(string name, int age) {
this->name = name;
this->age = age;
this->p = new int(10);
cout << "我是" << this->name << "我有两个参数的构造函数,我被执行了~" << endl;
}

~Person() {
delete this->p;
cout << "我是" << this->name << "的析构函数,我被执行了~" << endl;
}
};


int main() {

{
Person p1("程序员", 24);
Person p2(p1);

cout << p1.name << "的年龄是:" << p1.age << endl;
cout << p2.name << "的年龄是:" << p2.age << endl;

cout << "p1的地址是:" << &p1 << endl;
cout << "p2的地址是:" << &p2 << endl;
}

return 0;
}

2

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

class Person {
public:
string name = "xxx";
int age = 0;

//this指针是隐含在每一个非静态成员函数中的一个指针,使用时无需定义,指代当前对象,其本质是一个指针常量,指针的指向是该对象,不可以修改,但是指针指向的值可以修改。
//this指针的作用是指代该对象的成员变量或者成员函数,在构造函数中常有体现,当进行赋值时,由于作用域的原因,参数列表中的参数如果和成员变量同名,则会隐藏成员函数,如果想访问可以通过this指针。
//当要返回当前对象时,可以使用return *this,返回值仍是一个对象,因此还可以继续调用成员变量或者成员方法,体现出链式编程的思想。
Person(const Person& p) {
this->name = p.name;
this->age = p.age;
cout << "我是" << this->name << "的拷贝构造函数,我被执行了~" << endl;
}

Person(string name, int age) {
this->name = name;
this->age = age;
cout << "我是" << this->name << "我有两个参数的构造函数,我被执行了~" << endl;
}

~Person() {
cout << "我是" << this->name << "的析构函数,我被执行了~" << endl;
}
};


int main() {

{
Person p1("程序员", 24);
Person p2(p1);

cout << p1.name << "的年龄是:" << p1.age << endl;
cout << p2.name << "的年龄是:" << p2.age << endl;

cout << "p1的地址是:" << &p1 << endl;
cout << "p2的地址是:" << &p2 << endl;
}

return 0;
}

2

C++小结

  在这里给小伙伴们介绍了C++的基本面向对象的概念,虽然不是很难,但是非常重要,在这里为了方便起见,使用了public关键字,下一节会为大家详细介绍几种访问权限关键字。

-------------本文结束感谢您的阅读-------------
0%