C++ :类 和 对象 ※重点※(二)

简介: C++ :类 和 对象 ※重点※(二)

析构函数:

  析构函数同样也是特殊的成员函数,首先它的功能是和构造函数相反的,但他不是去销毁对象,对象销毁的工作是由编译器去做的,析构函数是去完成资源的清理工作,在对象销毁的时候自动调用


析构函数的特性:

  1. 函数名是在类名前面加上 ‘~’
  2. 无参数且无返回值
  3. 一个类有且只有一个析构函数,如果没有显示定义编译器会自动生成
  4. 一个对象生命周期结束,自动调用析构函数


大家看我下面的代码:我定义的对象里面的那三个成员变量会用到默认生成的析构函数嘛

class stu
{
public:
  stu(int a = 10,char c = 'A',int b = 20)
  {
    _a = a;
    _c = c;
    _b = b;
  }
  void print()
  {
    cout << _a << "-" << _c << "-" << _b << endl;
  }
private:
  int _a;
  char _c;
  int _b;
};
int main()
{
  stu s1;
}

 这三个成员变量是不是我们的对象销毁的时候,它会自动的销毁啊,那我析构函数是去完成资源的清理的,那是不是malloc 那几个函数 还有new 以及fopen 这些才是析构函数要处理的阿,


  注意:我们编译器默认生成的析构函数对malloc那些函数开辟的空间是不会自动去释放的,这些是需要我们自己手动去写的,这也是因为它无法判断一个指针到底是不是一块内存空间的地址,默认生成的析构函数对于内置类型不做处理,自定义类型调用它的析构函数:

01a6a6cefca74af1b9f4dba47f431d59.png

class stu
{
public:
  stu(int a = 10,char c = 'A',int b = 20)
  {
    _a = a;
    _c = c;
    _b = b;
  }
  void print()
  {
    cout << _a << "-" << _c << "-" << _b << endl;
  }
private:
  int _a;
  char _c;
  int _b;
};
int main()
{
  stu s1(20,'B',30);
    stu s2(40,'C',50);
}

大家觉得这里的 s1和s2 谁先析构呢?

当然是s2会先析构 ,记得:析构顺序和构造的顺序是相反的


拷贝构造函数:

  这个也是一个特殊的构造函数,它是构造函数的一种重载,它是拿一个已经定义好的对象去定义另外一个对象,同样他也是默认成员函数的一名,不写编译器自动生成:

对于内置类型(指针也是)会完成值(浅)拷贝,自定义类型会去调用它的拷贝构造(自己写的也会调用,哪怕你的函数里面没有写它的拷贝)

class stu
{
public:
    stu(stu& d)
    {
        _a = d._a;
    _c = d._c;
    _b = d._b;
    }
  stu(int a = 10,char c = 'A',int b = 20)
  {
    _a = a;
    _c = c;
    _b = b;
  }
  void print()
  {
    cout << _a << "-" << _c << "-" << _b << endl;
  }
private:
  int _a;
  char _c;
  int _b;
};
int main()
{
  stu s1(20,'B',30);
    stu s2(s1);//s2 s3都是调用的拷贝构造函数
    stu s3 = s2;
}

注意:拷贝构造函数的参数只有一个并且必须使用引用传参,如果是传值传参会发生无限递归

c82cc64acf044bf8ba74a711c1770e37.png   对于那写内置类型的拷贝,都是按字节直接拷贝过去的,对于自定义类型,拷贝初始化规定要调用拷贝构造函数,至于其中的原因就涉及深浅拷贝的问题,就好像我malloc的空间的指针,如果直接赋值(浅拷贝),我两个对象的指针都指向的是同一块空间,那我在调用析构函数的时候,同一块空间被释放两次不就出问题了嘛,我们就得自己去实现拷贝构造

如果我们拷贝的成员里面又数组会报错嘛? :答案是不会的,我们数组拷贝又不是把数组的地址拷贝过去,拷贝的是数组里面的内容

我们的拷贝构造函数同样也是构造函数,他是我们平常写的构造函数的一种重载,我们如果类里面写了拷贝构造函数,那么编译器默认生成的构造函数就不会生成了!


还有一个问题就是涉及const的问题,通常我们在写的时候,如果自己写错了,写成了对 d对象 的成员变量赋值,那不就出错了嘛,所以我们要在拷贝构造的参数用const修饰一下,其实像这样我们不会改变的对象,加上const是最好的

class stu
{
public:
    stu(const stu& d)
    {
        _a = d._a;
    _c = d._c;
    _b = d._b;
    }
  stu(int a = 10,char c = 'A',int b = 20)
  {
    _a = a;
    _c = c;
    _b = b;
  }
  void print()
  {
    cout << _a << "-" << _c << "-" << _b << endl;
  }
private:
  int _a;
  char _c;
  int _b;
};
int main()
{
  stu s1(20,'B',30);
    stu s2(s1);//s2 s3都是调用的拷贝构造函数
    stu s3 = s2;
}


目录
相关文章
|
1月前
|
编译器 C++
C++之类与对象(完结撒花篇)(上)
C++之类与对象(完结撒花篇)(上)
34 0
|
6天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
29 4
|
7天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
25 4
|
30天前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
27 4
|
30天前
|
编译器 C语言 C++
【C++打怪之路Lv4】-- 类和对象(中)
【C++打怪之路Lv4】-- 类和对象(中)
23 4
|
30天前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
21 1
|
1月前
|
存储 编译器 C语言
【C++打怪之路Lv3】-- 类和对象(上)
【C++打怪之路Lv3】-- 类和对象(上)
16 0
|
1月前
|
编译器 C++ 数据库管理
C++之类与对象(完结撒花篇)(下)
C++之类与对象(完结撒花篇)(下)
29 0
|
1月前
|
编译器 C++
C++之类与对象(3)(下)
C++之类与对象(3)(下)
32 0
|
1月前
|
存储 编译器 C++
【C++类和对象(下)】——我与C++的不解之缘(五)
【C++类和对象(下)】——我与C++的不解之缘(五)