• 【C++面向对象】2.构造函数、析构函数


    【 1. 构造函数 】

    • 类的构造函数是类的一种特殊的成员函数,它会 在每次创建类的新对象时执行
    • 构造函数的名称与类的名称是完全相同的,并且 不会返回任何类型,也不会返回 void。构造函数可 用于为某些成员变量设置初始值

    1.1 带参构造函数–传入数据

    • 法1
    class Complex
    {
    	private: 
    		double x;
    		double y;
    	public:
    		Complex(); //无参构造函数
    		Complex(double, double); //带参构造函数
    		void Complex_Printf(void); //输出函数
    };
    
    //带参构造函数--法1
    Complex::Complex(double a, double b) 
    {
    	x = a;
    	y = b;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 法2
    //带参构造函数--形式2-赋默认值
    Complex::Complex(double a=3.1, double b=6.2) 
    {
    	x = a;
    	y = b;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 法3
    //带参构造函数--法3
    Complex::Complex(double a,double b) :x(a), y(b) { };
    
    • 1
    • 2
    • 法4
    //带参构造函数--法4-赋默认值
    Complex::Complex(double a=3.1,double b=6.2) :x(a), y(b) { };
    
    • 1
    • 2

    1.2 无参构造函数–不传入数据

    • 法1
    class Complex
    {
    	private: 
    		double x;
    		double y;
    	public:
    		Complex(); //无参构造函数
    		Complex(double, double); //带参构造函数
    		void Complex_Printf(void); //输出函数
    };
    //无参构造函数:默认值x=2,y=1
    Complex::Complex()
    {
    	x=2;
    	y=1;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 法2
    //无参构造函数:默认值x=2,y=1
    Complex::Complex() :x(2), y(1) { };
    
    • 1
    • 2

    1.3 实例1

    #include 
    
    using namespace std;
    
    class Box
    {
       private:
          double length;     // Length of a box
          double breadth;    // Breadth of a box
          double height;     // Height of a box
       public:
       	
       	  // 带参构造函数-法1 
          Box(double l, double b, double h)
          {
             length = l;
             breadth = b;
             height = h;
          }
          /*
          
          // 带参构造函数-法2-赋默认值
          Box(double l=2.0, double b=3.0, double h=4.0)
          {
             length = l;
             breadth = b;
             height = h;
          }
          // 带参构造函数-法3 
          Complex::Complex(double l, double b, double h) :length(l), breadth(b),height(h) { };
    
          //带参构造函数-法4-赋默认值
    	  Complex::Complex(double l=2.0, double b=3.0, double h=4.0) :length(l), breadth(b),height(h) { };
          
          //无参构造函数-法1 
          Complex::Complex()
          {
    	     x=2;
    	  	 y=1;
          };
          
          // 无参构造函数-法2
    	  Complex::Complex() :x(2), y(1) { };
     
          */
          
          double Volume()
          {
             return length * breadth * height;
          }
    };
    
    int main(void)
    {
       
       Box Box1(1.0,2.2,3.0);
       /* 适用于: 
       带参构造函数-法1
       带参构造函数-法2-赋给定值
       带参构造函数法3
       带参构造函数-法4-赋给定值
       */ 
       
    //   Box Box1;
       /* 适用于: 
       带参构造函数-法2-赋默认值
       带参构造函数-法4-赋默认值
       无参构造函数法1
       无参构造函数法2
       */  
         
       cout << Box1.Volume() <<endl;
       
       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
    • 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

    1.4 实例2

    // 【Complex.h】
    #pragma once
    
    class Complex
    {
    	private: 
    		double x;
    		double y;
    	public:
    		Complex(); //无参构造函数
    		Complex(double, double); //带参构造函数
    		void Complex_Printf(void); //输出函数
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    // 【 Complex.cpp 】
    #include "Complex.h"
    #include 
    using namespace std;
    
    //无参构造函数:默认值x=2,y=1
    Complex::Complex() :x(2), y(1) {};
    
    //带参构造函数:赋初值
    Complex::Complex(double a, double b) 
    {
    	x = a;
    	y = b;
    }
    
    //输出函数,根据实部x和虚部y,输出对应的复数
    void  Complex::  Complex_Printf(void)
    {
    	if      (!x && !y)        cout << '0' << endl;			     //{0}  {0}   :0
    	else if (x  && !y)        cout << x << endl;                 //{≠0}{0}   :x
    	else if (!x && y == -1)   cout << '-i' << endl;              //{0}  {-1}  :-i
    	else if (!x && y == 1)    cout << 'i' << endl;               //{0}  {1}	  :i
    	else if (!x)              cout<<y<<'i'<<endl;				 //{0}  {else}:yi
    	else if (x && y == 1)     cout << x << "+i" << endl;         //{≠0}{1}   :x+i
    	else if (x && y == -1)    cout << x << "-i" << endl;         //{≠0}{-1}  :x-i
    	else if (y > 0)           cout << x << '+' << y << 'i'<<endl;//{≠0}{>0}  :x+yi ,y>0
    	else                      cout << x <<y << 'i' << endl;		 //{≠0}{<0}  :x-yi ,y<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
    // 【 Main.cpp 】
    #include 
    #include "Complex.h"
    using namespace std;
    
    int main(void)
    {
    	Complex a;
    	Complex b(0, 0);
    	Complex c(0.2, 3.7);
    	Complex d(0, 1);
    	Complex e(2, 0);
    	Complex f(3, -5);
    	a.Complex_Printf();
    	b.Complex_Printf();
    	c.Complex_Printf();
    	d.Complex_Printf();
    	e.Complex_Printf();
    	f.Complex_Printf();
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述

    【 2. 拷贝构造函数 】

    • 拷贝构造函数是一种特殊的构造函数,它在创建对象时,是 使用同一类中之前创建的对象来初始化新创建的对象。
    • 如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。
    • 拷贝构造函数通常用于:
      • 通过 使用另一个同类型的对象来初始化新创建的对象
      • 复制对象把它作为参数传递给函数。
      • 复制对象,并从函数返回这个对象。
    • 拷贝构造函数的常见形式:
    classname (const classname &obj) 
    {
       // 构造函数的主体
    }
    
    • 1
    • 2
    • 3
    • 4
    • 实例1:
    • Line line(10); // 创建一个Line类的对象line,会调用构造函数,输出 “调用构造函数”
    • display(line); // 使用 line 作为参数传入display函数中时,系统首先会调用拷贝构造函数为 line 进行复制创建得到一个临时副本,输出 “调用拷贝构造函数并为指针 ptr 分配内存”
      系统使用该副本在 display 函数中 进行操作,输出 “line 大小 :10”,display 函数结束后该副本作为局部变量被回收,输出 “释放内存”
    • 对象 Line 在主程序结束前 也将被回收,输出 “释放内存”
    #include 
    
    using namespace std;
    
    class Line
    {
       public:
          int getLength( void );
          Line( int len );             // 简单的构造函数
          Line( const Line &obj);      // 拷贝构造函数
          ~Line();                     // 析构函数
    
       private:
          int *ptr;
    };
    
    // 构造函数
    Line::Line(int len)
    {
        cout << "调用构造函数" << endl;
        // 为指针分配内存
        ptr = new int;
        *ptr = len;
    }
    
    // 拷贝构造函数 
    Line::Line(const Line &obj)
    {
        cout << "调用拷贝构造函数并为指针 ptr 分配内存" << endl;
        ptr = new int;
        *ptr = *obj.ptr; // 拷贝值
    }
    
    // 析构函数 
    Line::~Line(void)
    {
        cout << "释放内存" << endl;
        delete ptr;
    }
    
    // 成员函数 
    int Line::getLength( void )
    {
        return *ptr;
    }
    
    // 外部函数 
    void display(Line obj); 
    
    // 程序的主函数
    int main( )
    {
       Line line(10);
       display(line);
       return 0;
    }
    
    // 一个外部函数 
    void display(Line obj)
    {
       cout << "line 大小 : " << obj.getLength() <<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

    在这里插入图片描述

    • 实例2:
    • Line line1(10); // 创建一个Line类的对象line1,会调用构造函数,输出 “调用构造函数”
    • Line line2 = line1; // 创建一个Line类的对象line2 且 lin2 是由 lin1 复制得到,即调用了拷贝构造函数,输出 “调用拷贝构造函数并为指针 ptr 分配内存”
    • display(line1); // 使用 line1 作为参数传入display函数中时,系统首先会调用拷贝构造函数为 line1 进行复制创建得到一个临时副本,输出 “调用拷贝构造函数并为指针 ptr 分配内存”
      系统使用该副本在 display 函数中 进行操作,输出 “line 大小 :10”
      display 函数结束后该副本作为局部变量被回收,输出 “释放内存”
    • 同样地, display(line2); // 使用 line2 作为参数传入display函数中时,系统首先会调用拷贝构造函数为 line2 进行复制创建得到一个临时副本,输出 “调用拷贝构造函数并为指针 ptr 分配内存”
      系统使用该副本在 display 函数中 进行操作,输出 “line 大小 :10”
      display 函数结束后该副本作为局部变量被回收,输出 “释放内存”
    • 对象 Line1 和Line2 在主程序结束前 也将被回收,分别输出 “释放内存”
    #include 
    
    using namespace std;
    
    class Line
    {
       public:
          int getLength( void );
          Line( int len );             // 简单的构造函数
          Line( const Line &obj);      // 拷贝构造函数
          ~Line();                     // 析构函数
    
       private:
          int *ptr;
    };
    
    // 构造函数
    Line::Line(int len)
    {
        cout << "调用构造函数" << endl;
        // 为指针分配内存
        ptr = new int;
        *ptr = len;
    }
    
    // 拷贝构造函数 
    Line::Line(const Line &obj)
    {
        cout << "调用拷贝构造函数并为指针 ptr 分配内存" << endl;
        ptr = new int;
        *ptr = *obj.ptr; // 拷贝值
    }
    
    // 析构函数 
    Line::~Line(void)
    {
        cout << "释放内存" << endl;
        delete ptr;
    }
    
    // 成员函数 
    int Line::getLength( void )
    {
        return *ptr;
    }
    
    void display(Line obj); 
    
    
    // 程序的主函数
    int main( )
    {
       Line line1(10);
    
       Line line2 = line1; // 这里也调用了拷贝构造函数
    
       display(line1);
       display(line2);
    
       return 0;
    }
    
    // 外部函数 
    void display(Line obj)
    {
       cout << "line 大小 : " << obj.getLength() <<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

    在这里插入图片描述

    【 3. 析构函数

    • 类的析构函数是类的一种特殊的成员函数, 类的析构函数会在每次删除所创建的对象时执行。

    • 析构函数的 名称与类的名称是完全相同的,只是在前面加了个 波浪号(~) 作为前缀,它 不会返回任何值,也 不能带有任何参数

    • 析构函数 有助于在跳出程序(比如关闭文件、释放内存等)前释放资源

    • 如果程序里没有构造函数和析构函数,编译器在编译的时候会自动生成构造函数和析构函数,只是函数内没有任何操作。

    • 实例

    #include 
    
    using namespace std;
    
    class Line
    {
       public:
          void setLength( double len );
          double getLength( void );
          Line();   // 这是构造函数声明
          ~Line();  // 这是析构函数声明
    
       private:
          double length;
    };
    
    // 成员函数定义,包括构造函数
    Line::Line(void)
    {
        cout << "Object is being created" << endl;
    }
    Line::~Line(void)
    {
        cout << "Object is being deleted" << endl;
    }
    
    void Line::setLength( double len )
    {
        length = len;
    }
    
    double Line::getLength( void )
    {
        return length;
    }
    // 程序的主函数
    int main( )
    {
       Line line;
    
       // 设置长度
       line.setLength(6.0); 
       cout << "Length of line : " << line.getLength() <<endl;
    
       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

    在这里插入图片描述

  • 相关阅读:
    判断文件是否为DICOM文件
    Java IO 与 NIO:高效的输入输出操作探究
    AI来了,会不会失业?
    5分钟学会canvas的使用
    Debian11之基于kubeadm安装K8S集群
    Datawhale ChatGPT基础科普
    鸿蒙OS开发:【一次开发,多端部署】(音乐专辑主页)
    [GO语言基础] 一.为什么我要学习Golang以及GO语言入门普及
    python中dateutil库用法详解
    python 动态导入模块,实现模块热更新
  • 原文地址:https://blog.csdn.net/qq_44431690/article/details/133935083