构造函数和析构函数

构造函数

是一种特殊的方法,主要用来在创建对象时初始化对象,即为对象成员变量赋初始值,总与new运算符一起使用。一个类可以有多个构造函数,可根据其参数个数的不同或参数类型的不同区分它们。

1)、类的成员函数名和类名相同

2)、定义时可带有参数

3)、没有返回值类型声明

4)、在没有提供构造函数时,通过类名声明对象会调用默认的构造函数

5)、一般情况下我们需要手工调用构造函数,写了构造函数就必须要用。

析构函数

与构造函数相反,当对象结束其生命周期时,如对象所在的函数已经调用完毕时,系统会自动执行析构函数。一般建立一个对象需要用到new自动调用构造函数开辟一片内存空间,delete会自动调用析构函数释放内存。

1)、C++中的类可以定义一个特殊的成员函数清理对象,这个特殊的成员函数叫析构函数

2)、析构函数没有任何参数和返回值类型

3)、析构函数在对象销毁时自动调用

无参构造函数

构造函数没有形参列表,即为无参

Class MyTest
{
public:
    MyTest()
    {
        cout<<"我是无参构造函数"<<endl;
    }
    ~MyTest()
    {
        cout<<"我是析构函数"<<endl;
    }
private:
    //......
}

带参构造函数

有形参列表,即为有参

Class MyTest
{
public:
    MyTest(int a,int b)
    {
        m_a = a;
        m_b = b;
        cout<<"我是有参构造函数"<<endl;
    }
    ~MyTest()
    {
        cout<<"我是析构函数"<<endl;
    }
    
    int GetA()
    {
        return m_a;
    }
private:
    int m_a,m_b;
}

Copy构造函数

如果用相同类型的另外一个对象来初始化此对象,则调用Copy构造函数,这个知识点后面会专门来讲

Class MyTest
{
public:
    MyTest(const MyTest& obj)
    {
        cout<<"我是赋值构造函数函数"<<endl;
    }
    ~MyTest()
    {
        cout<<"我是析构函数"<<endl;
    }
private:
    //......
}

构造函数的调用

无参调用

MyTest t;

括号法

MyTest t1(1);//带有一个参数的构造函数
MyTest t2(1,2);//带有两个参数的构造函数
......

等号法

MyTest t1 = (1,2,3,4,5);
MyTest t2 = 5;

//用法相同,调用一个参数的构造函数把5传给形参

直接调用

MyTest t1 = MyTest(1);//调用一个参数的构造函数
MyTest t2 = MyTest(1,2);//调用两个参数的构造函数
.......

为什么需要构造函数和析构函数

对于一种特别的类成员,比如复杂,内存占比大这样的成员变量我们一般不会放到栈区,而是希望出现在堆区。

在C语言中如果要声明一个数组变量并初始化它,我们不会直接定义一个数组成员,而会定义一个指针,让他指向堆区中的数组内存。虽然这个堆中的数组不是对象的成员变量,但是我们可以通过定义的指针去访问这个数组。在这个过程中我们要初始化的有两个东西,一个是指针变量,一个是堆中的数组,一般会怎样初始化,是下面这样吗?

//栈区数组
char buf[] = "Hello World!";
char *pbuf = buf;

或者复杂一点,动态分配堆内存空间(生成一个指定长度的字符串),存在于堆中,当main函数调用结束之后如果不去手动释放内存,则会出现内存泄漏,所以必须提供free方法。整个过程是不是感觉很复杂。

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#pragma warning(disable : 4996)

int main(int argc, char** argv)
{
    int i, n;

    scanf("%d", &n);
	
    char *pbuf = (char *)malloc(n+1);

    for (i = 0; i < n; i++)
    {
        pbuf[i] = rand() % 26 + 'a';
    }
    pbuf[n] = '\0';
    printf(pbuf);
    free(pbuf);

    printf("hello.. \n");
    system("pause");
    return 0;
}

注意:上面的char *pbuf = (char *)malloc(n+1);为什么要“+1”

在字符数组中‘\0’是一个占位标识符,存在于字符数组最后,判定字符数组结束的标识,标识这串字符到结尾了。

char buf[6] = "Hello!"    在内存中buf为“Hello!\0”,‘\0’占有空间但不会被我们看到。

因此我们在动态创建字符数组时,字符长度要在分配长度基础上额外“+1”。不然会出现程序错误。

那么在C++中我们要怎么申请堆内存字符数组呢?C++提供了一种解决捷径。就是构造函数,在初始化对象时会自动调用构造函数。如果在构造函数中这样写。

#include <iostream>
using namespace std;
#pragma warning(disable : 4996)

class Test
{
public:
    Test()
    {
        m_name = new char[100];
        strcpy(m_name, "Hello World!");
    }
    ~Test()
    {
        delete m_name;
    }
public:
    char *m_name;
};

void main()
{
    Test t;
    cout << t.m_name << endl;
    system("pause");
}

是不是简单多了,当main函数执行完成时会自动调用类的析构函数,只要在析构函数中使用delete这个运算符释放内存就一切简单解决了。相比C是不是又方便又高效。

总结

1)当类中没有定义任何一个构造函数时,c++编译器会提供默认无参构造函数和默认拷贝构造函数

2)当类中定义了拷贝构造函数时,c++编译器不会提供无参数构造函数

3) 当类中定义了任意的非拷贝构造函数(即:当类中提供了有参构造函数或无参构造函数),c++编译器不会提供默认无参构造函数

4 )默认拷贝构造函数成员变量简单赋值

5)只要你写了构造函数,那么你必须用。

构造析构阶段性总结

1)构造函数是C++中用于初始化对象状态的特殊函数

2)构造函数在对象创建时自动被调用

3)构造函数和普通成员函数都遵循重载规则

4)拷贝构造函数是对象正确初始化的重要保证

5)必要的时候,必须手工编写拷贝构造函数

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值