• C++面向对象OOP-构造函数


    构造函数作用

    构造函数在创建对象的时候自动调用,可以让对象进行初始化工作。

    构造函数特征

    • 自动调用,在创建对象的时候编译器自动调用
    • 构造函数名和类名相同
    • 构造函数没有返回值
    • 可以有多个构造函数(类似函数重载)

    构造函数种类

    • 默认构造函数
    • 自定义构造函数
    • 拷贝构造函数
    • 赋值构造函数

    默认构造函数

    编译器合成的默认构造函数

    没有手动创建默认构造函数的时候,编译器会去自动合成构造函数

    • 合成默认构造函数使用类内初始化数据去初始化数据
    • 如果没有类内初始化数据,那么合成构造函数内就是空的什么都不做

    默认构造函数
    程序:

    Student.h

    #pragma once
    #include
    #include
    
    using namespace std;
    
    class Student
    {
    public:
    	void describion();
    
    private:
    	// 类内初始化
    	// 创建对象的时候如果没有构造函数那边编译器会自己合成默认构造函数并且用这些数据来初始化对象
    	// 编译器和合成的默认构造函数和手动定义的默认构造函数区别是:
    	//    编译器合成的只会拿这些类内初始化数据去初始化对象
    	//    手动定义的默认构造函数如果有初始化数据的时候也可以用其他数据去覆盖初始化数据,也就是说数据初始化的值以构造函数内为准
    	int age = 12;
    	char name[20] = "bian";
    	string sex = "男";
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    Student.cpp
    #include "Student.h"
    
    void Student::describion() {
    	cout << this->name << " " << this->sex << " " << this->age << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    main.cpp
    #include "Student.h"
    
    using namespace std;
    
    int main() {
    	Student s1;  // 创建对象调用默认构造函数
    	s1.describion();
    
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    结果:

    bian 男 12
    请按任意键继续. . .

    手动定义的默认构造函数

    手动定义的默认构造函数特点:Student::Student()
    手动定义的默认构造函数和编译器和成的默认构造函数没太大区别。
    唯一的区别:手动默认构造函数可以使用类内初始化的值,也可以不使用类内初始化的值。

    程序:

    Student.h

    #pragma once
    #include
    #include
    
    using namespace std;
    
    class Student
    {
    public:
    	Student();
    	void describion();
    
    private:
    	// 类内初始化
    	int age = 12;
    	char name[20] = "bian";
    	string sex = "男";
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    Student.cpp
    #include "Student.h"
    
    // 自定义默认构造函数
    Student::Student() {
    
    	// 使用类内初始化数据来初始化
    	// 其实这种就是编译器合成默认构造函数
    	this->age = age;
    	strcpy_s(this->name, 20, "bian");
    	this->sex = sex;  
    
    	/*
    	// 使用其他数据来初始化对象,此做法会覆盖类内初始化的设置值
    	this->age = 14;
    	strcpy_s(this->name, 20, "wang");
    	this->sex = "女";
    	*/
    }
    
    
    void Student::describion() {
    	cout << this->name << " " << this->sex << " " << this->age << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    main.cpp
    #include "Student.h"
    
    using namespace std;
    
    int main() {
    	Student s1;  // 创建对象调用默认构造函数
    	s1.describion();
    
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    结果:

    bian 男 12
    请按任意键继续. . .

    自定义带参数的构造函数

    自定义带参数的构造函数特点:Student::Student(int age, const char name)*
    带参数,可以重载。

    代码:

    Student.h

    #pragma once
    #include
    #include
    
    using namespace std;
    
    class Student
    {
    public:
    	Student();  // 默认构造函数
    	Student(int age, const char* name);  // 自定义带参构造函数
    	Student(int age, const char* name, string sex);  // 自定义带参构造重载函数
    
    	void describion();
    
    private:
    	// 类内初始化
    	int age = 12;
    	char name[20] = "bian";
    	string sex = "男";
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    Student.cpp

    #include "Student.h"
    
    // 自定义默认构造函数
    Student::Student() {
    	// 使用类内初始化数据来初始化
    	// 其实这种就是编译器合成默认构造函数
    	cout << __FUNCTION__ << endl;
    	cout << "自定义默认构造函数" << endl;
    
    	this->age = age;
    	strcpy_s(this->name, 20, "bian");
    	this->sex = "未知";
    }
    
    // 自定义带参构造函数
    Student::Student(int age, const char* name) {
    	cout << __FUNCTION__ << endl;
    	cout << "自定义带参构造函数" << endl;
    
    	this->age = age;
    	strcpy_s(this->name, 20, name);
    }
    
    // 自定义带参构造重载函数
    Student::Student(int age, const char* name, string sex) {
    	cout << __FUNCTION__ << endl;
    	cout << "自定义带参构造重载函数" << endl;
    
    	this->age = age;
    	strcpy_s(this->name, 20, name);
    	this->sex = sex;
    }
    
    void Student::describion() {
    	cout << this->name << " " << this->sex << " " << this->age << endl;
    	cout << 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

    main.cpp

    #include "Student.h"
    
    using namespace std;
    
    int main() {
    	Student s1;  // 调用自定义默认构造函数
    	s1.describion();
    
    	Student s2(13, "wang");  // 调用自定义带参构造函数
    	s2.describion();
    
    	Student s3(14, "gao", "女");  // 调用自定义带参构造函数(重载)
    	s3.describion();
    
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    结果:

    Student::Student
    自定义默认构造函数
    bian 未知 12
    
    Student::Student
    自定义带参构造函数
    wang 男 13
    
    Student::Student
    自定义带参构造重载函数
    gao 女 14
    
    请按任意键继续. . .
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    为什么会出现 wang 男 13,可以思考下这个男。答案在特别注意。

    拷贝构造函数

    拷贝构造函数特点:Student::Student(const Student& other)
    浅拷贝是针对在堆区开辟内存的数据,深拷贝重新开辟内存存数据,浅拷贝直接把原来的堆区拿过来用

    合成拷贝构造函数

    合成拷贝构造函数是编译器自动合成的属于浅拷贝

    自定义拷贝构造函数

    自定义拷贝构造函数可以实现深拷贝
    Student.h

    #pragma once
    #include
    #include
    
    using namespace std;
    
    class Student
    {
    public:
    	Student();  // 默认构造函数
    	Student(int age, const char* name);  // 自定义带参构造函数
    	Student(int age, const char* name, string sex);  // 自定义带参构造重载函数
    
    	Student(const Student& other);  // 拷贝构造函数
    
    	void describion();
    
    private:
    	// 类内初始化
    	int age = 12;
    	char* name;
    	string sex = "男";
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    Student.cpp

    #include "Student.h"
    
    // 自定义默认构造函数
    Student::Student() {
    	// 使用类内初始化数据来初始化
    	// 其实这种就是编译器合成默认构造函数
    	cout << __FUNCTION__ << endl;
    	cout << "自定义默认构造函数" << endl;
    
    	this->age = age;
    	this->name = new char[20];
    	strcpy_s(this->name, 20, "bian");
    	this->sex = "未知";
    }
    
    // 自定义带参构造函数
    Student::Student(int age, const char* name) {
    	cout << __FUNCTION__ << endl;
    	cout << "自定义带参构造函数" << endl;
    
    	this->age = age;
    	this->name = new char[20];
    	strcpy_s(this->name, 20, name);
    }
    
    // 自定义带参构造重载函数
    Student::Student(int age, const char* name, string sex) {
    	cout << __FUNCTION__ << endl;
    	cout << "自定义带参构造重载函数" << endl;
    
    	this->age = age;
    	this->name = new char[20];
    	strcpy_s(this->name, 20, name);
    	this->sex = sex;
    }
    
    // 拷贝构造函数
    Student::Student(const Student& other) {
    	cout << __FUNCTION__ << endl;
    	cout << "拷贝构造函数" << endl;
    
    	// 浅拷贝,堆区地址还是以前的,其实编译器合成的拷贝构造函数就是这个
    	this->age = other.age;
    	this->name = other.name;
    	this->sex = other.sex;
    
    
    	// 深拷贝部分主要是堆区空间重新开辟
    	this->age = other.age;
    	// 重新开辟堆区
    	this->name = new char[20];
    	strcpy_s(this->name, 20, other.name);
    
    	this->sex = other.sex;
    }
    
    void Student::describion() {
    	cout << this->name << " " << this->sex << " " << this->age << endl;
    	cout << 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
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    main.cpp

    #include "Student.h"
    
    using namespace std;
    
    // 拷贝构造函数调用第二种时机函数形参是值传递而不是引用
    void test1(Student other) {
    	cout << __FUNCTION__ << endl;
    	cout << endl;
    }
    
    // 拷贝构造函数调用第三种时机返回值是值传递
    Student test2(const Student& other) {
    	cout << __FUNCTION__ << endl;
    	cout << endl;
    
    	return other;
    }
    
    int main() {
    	Student s1;  // 调用自定义默认构造函数
    	s1.describion();
    
    	Student s2(13, "wang");  // 调用自定义带参构造函数
    	s2.describion();
    
    	Student s3(14, "gao", "女");  // 调用自定义带参构造函数(重载)
    	s3.describion();
    
    	// 拷贝构造函数:调用时机1、利用已有对象创建新对象
    	Student s4 = s2;
    	s4.describion();
    	Student s5(s3);
    	s5.describion();
    
    	// 拷贝构造函数:调用时机2、函数参数的值传递
    	test1(s5);
    
    	// 拷贝构造函数:调用时机3、函数返回值的值传递
    	test2(s5);
    
    	cout << endl;
    	// 拷贝构造函数:代用时机4、数组值时对象
    	Student s6[2] = { s1, s2 };
    
    	system("pause");
    	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
    • 45
    • 46
    • 47

    结果:

    Student::Student
    自定义默认构造函数
    bian 未知 12
    
    Student::Student
    自定义带参构造函数
    wang 男 13
    
    Student::Student
    自定义带参构造重载函数
    gao 女 14
    
    Student::Student
    拷贝构造函数
    wang 男 13
    
    Student::Student
    拷贝构造函数
    gao 女 14
    
    Student::Student
    拷贝构造函数
    test1
    
    test2
    
    Student::Student
    拷贝构造函数
    
    Student::Student
    拷贝构造函数
    Student::Student
    拷贝构造函数
    请按任意键继续. . .
    
    • 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

    结果解析:
    在这里插入图片描述

    拷贝构造函数的调用时间

    程序演示已经在自定义拷贝构造函数中写了。

    • 使用已有对象创建新对象
    • 函数参数是对象值传递
    • 函数返回值是对象值传递
    • 数组成员是对象

    赋值构造函数(operator=)

    赋值构造函数特点:Student& operator=(const Student& other)
    利用已有对象修改已有对象(f2 = f1;)
    重载=运算符

    程序:
    Student.h

    #pragma once
    #include
    #include
    
    using namespace std;
    
    class Student
    {
    public:
    	Student();  // 默认构造函数
    	Student(int age, const char* name);  // 自定义带参构造函数
    	Student(int age, const char* name, string sex);  // 自定义带参构造重载函数
    
    	Student(const Student& other);  // 拷贝构造函数
    
    	Student& operator=(const Student& other);  // 赋值拷贝构造函数
    
    	void describion();
    
    private:
    	// 类内初始化
    	int age = 12;
    	char* name;
    	string sex = "男";
    };
    
    • 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

    Student.cpp

    #include "Student.h"
    
    // 自定义默认构造函数
    Student::Student() {
    	// 使用类内初始化数据来初始化
    	// 其实这种就是编译器合成默认构造函数
    	cout << __FUNCTION__ << endl;
    	cout << "自定义默认构造函数" << endl;
    
    	this->age = age;
    	this->name = new char[20];
    	strcpy_s(this->name, 20, "bian");
    	this->sex = "未知";
    }
    
    // 自定义带参构造函数
    Student::Student(int age, const char* name) {
    	cout << __FUNCTION__ << endl;
    	cout << "自定义带参构造函数" << endl;
    
    	this->age = age;
    	this->name = new char[20];
    	strcpy_s(this->name, 20, name);
    }
    
    // 自定义带参构造重载函数
    Student::Student(int age, const char* name, string sex) {
    	cout << __FUNCTION__ << endl;
    	cout << "自定义带参构造重载函数" << endl;
    
    	this->age = age;
    	this->name = new char[20];
    	strcpy_s(this->name, 20, name);
    	this->sex = sex;
    }
    
    // 拷贝构造函数
    Student::Student(const Student& other) {
    	cout << __FUNCTION__ << endl;
    	cout << "拷贝构造函数" << endl;
    
    	// 浅拷贝,堆区地址还是以前的
    	//this->age = other.age;
    	//this->name = other.name;
    	//this->sex = other.sex;
    
    
    	// 深拷贝部分主要是堆区空间重新开辟
    	this->age = other.age;
    	// 重新开辟堆区
    	this->name = new char[20];
    	strcpy_s(this->name, 20, other.name);
    	this->sex = other.sex;
    }
    
    // 赋值拷贝构造函数
    Student& Student::operator=(const Student& other) {
    	cout << __FUNCTION__ << endl;
    	cout << "赋值拷贝构造函数" << endl;
    
    	if (this == &other) {
    		return *this;  // 防止出现f1=f1
    	}
    
    	// 浅拷贝,堆区地址还是以前的
    	//this->age = other.age;
    	//this->name = other.name;
    	//this->sex = other.sex;
    
    
    	// 深拷贝部分主要是堆区空间重新开辟
    	this->age = other.age;
    	// 重新开辟堆区
    	this->name = new char[20];
    	strcpy_s(this->name, 20, other.name);
    	this->sex = other.sex;
    
    	return *this;
    }
    
    void Student::describion() {
    	cout << this->name << " " << this->sex << " " << this->age << endl;
    	cout << 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
    • 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

    main.cpp

    #include "Student.h"
    
    using namespace std;
    
    int main() {
    
    	Student s1(14, "gao", "女");  // 调用自定义带参构造函数(重载)
    	s1.describion();
    
    	// 调用赋值拷贝构造函数
    	Student s2;
    	s2.describion();
    	s2 = s1; 
    	s2.describion();
    
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    结果:

    Student::Student
    自定义带参构造重载函数
    gao 女 14
    
    Student::Student
    自定义默认构造函数
    bian 未知 12
    
    Student::operator =
    赋值拷贝构造函数
    gao 女 14
    
    请按任意键继续. . .
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    特别注意:

    1、当存在类内初始值的时候,除了赋值拷贝构造函数外,其他的构造函数(默认构造函数、自定义参数构造函数、拷贝构造函数)在执行构造函数前都会先执行下数据初始值。
    在这里插入图片描述

    2、初始化列表只存在构造函数中(成员数据、父类对象可以使用初始化列表初始化)

  • 相关阅读:
    K8S:本质
    基于Python-sqlparse的SQL表血缘追踪解析实现
    (done) 什么是特征值和特征向量?如何求特征值的特征向量 ?如何判断一个矩阵能否相似对角化?
    FME在变更地类流向统计中的应用
    SOME/IP 协议介绍(三)参数和数据结构的序列化
    【gitlab】从其他仓库创建项目
    被火车撞了都不能忘记的几道题(你会了吗?)
    Secureboot从入门到精通
    速盾:ddos攻击类型有哪些?
    剑指 Offer 27. 二叉树的镜像
  • 原文地址:https://blog.csdn.net/qq_14824921/article/details/127352926