首页 > 编程语言 >C++入门到放弃(07)——构造函数和析构函数

C++入门到放弃(07)——构造函数和析构函数

时间:2023-08-02 23:39:35浏览次数:54  
标签:初始化 const 函数 int C++ test 构造函数 07

​1.构造函数和析构函数是什么

1.1构造函数

通常一个类,其内部包含有变量和函数,当我们想要使用类的时候,总是会不得不面临这样一个问题,需要对类进行初始化,否则内部这些变量就会是随机值,导致程序出现异常。

为此,我们需要在使用类之前对它进行初始化,C++就提供了这样一类特殊的函数——构造函数,它在创建类的时候会被自动调用,对类进行初始化。

1.2析构函数

析构函数和构造函数类似,它会在类对象被销毁时自动调用,主要负责一些清理工作。通常在函数结束后,在当前函数内生成的那些类就会被调用。

如果构造函数没有使用new来创建堆内存对象的话,一般是不需要析构函数做任何处理的,否则需要在析构函数内使用delete来释放这些堆内存,以避免出现内存泄漏的风险。

2.构造函数

2.1.基本形式

举个例子,测试类当中有三个变量a、b、c需要初始化,可以这样写。

class test {
public:
    test(int a, int b, int c = 0)
        : m_a(a),m_b(b),m_c(c)
    {
        m_a = 100;
        //return;    错误,构造函数不允许return
    }
    void display() {
        cout << m_a << " " << m_b << " " << m_c << endl;
    }
private:
    int m_a;    // m_a = 1,再次赋值,m_a = 100
    int m_b;    // m_b = 2
    int m_c;    // m_c没有输入,默认 = 0
};

//初始化并输出
test t(1,2):
t.display();

基本格式是 classname() : {} 或 classname() {}

由以下几个特征:

1.没有返回类型,同时也不能有返回值;

2.括号()中间是函数的输入变量,可以在后面赋值,这样输入就会在没有输入的情况下赋默认值(这一条适用于所有函数,但是必须保证默认赋值变量的顺序是从后往前);

3.冒号:后面的内容是初始化列表,使用A(B)的方式,将B赋值给A,用逗号,隔开,但最后一个变量不能有逗号,这段内容写在()和{}中间。需要注意的是,初始化列表不是必须的,可以完全不使用初始化列表,全部都在{}内赋值也可以。

4.花括号{}中间的内容,就像正常的函数实现一样,在初始化时,会执行一次内部的程序。

因此,最后输出的结果如注释写的那样:m_a = 100, m_b = 2, m_c = 0。

2.2.特殊构造函数

构造函数是运行重载的,下面这些构造函数本质和其它构造函数没有任何区别,只是这些用法比较多,从而有了一些特殊的名称而已。

默认构造函数:

当我们没有写任何构造函数的时候,系统也会隐含存在一个构造函数,只不过它的输入变量、初始化列表,以及函数内容都是空的,不进行任何初始化操作。如果我们写一个构造函数不带任何输入,那么就会覆盖掉默认的构造函数,使用人工编写的构造函数。

class test {
public:
    //默认构造函数,就算不写出来,程序也会默认附带这样一个构造函数
    test() {}
private:
    int m_a;
};
//初始化
test t;

拷贝构造函数:

以相同的类来作为当前类的唯一输入的构造函数。这里有两个关键点,相同的类唯一输入,说大白话就是,将同样的类A拷贝到B。至于如何进行初始化,那就要针对不同的类来考虑了,通常都需要手动对类的内部变量进行一一拷贝赋值。

class test {
public:
    test(const test& other) 
        //将other中的所有值赋值给当前类
        : m_a(other.m_a)
           m_b(other.m_b)
    {}
private:
    int m_a; int m_b;
};
//初始化
test t1;
test t2(t1);

转换构造函数:

和拷贝构造函数类似,只不过是将另外一个类,转化为当前类,那么情况就更为复杂,需要依据使用场景和类的具体内容,进行初始化赋值。

例如这个例子,需要用test_a给test_b赋值,但是又无法访问a的私有成员,就需要使用get_a函数,且我们不希望更改test_a的内容加上了const,但是赋值时又需要去掉const,从而使用const_cast修饰。

class test_a {
public:
    test_a(int a) 
        : m_a(a)
    {}
    const int get_a() { return m_a; }
private:
    int m_a;
};

class test_b {
    test_b(const test_a& t)
        : m_b(const_cast<test_a&>(t).get_a())
    {}
private:
    int m_b;
};

test_a ta(1);
test_b tb(ta);

3.析构函数

class test {
public:
    test() { }
    ~test() { }
};

基本格式是 ~classname() {} 

由以下几个特征:

1.没有返回类型,同时也不能有返回值;

2.类名前面需要加一个~,代表析构函数名;

3.花括号{}中间的内容,就像正常的函数实现一样,在类被销毁时,会执行一次内部的程序。

注意:通常情况下,我们不会主动调用析构函数,都是让系统自动去调用。

 

析构函数使用场景一般像下面这样,用于释放构造时占用的堆内存:

class test{
public:
    test() : m_p(new int) {}
    ~test() { delete m_p; }
private:
    int* m_p;
}

4.特殊情况

上面的情况都只适用于常规的情况,在某些特殊场景下,有些特殊操作,包括:

const类成员static类成员explicit显式构造private构造函数private析构函数等,下一期在对这些特殊情况进行说明,

标签:初始化,const,函数,int,C++,test,构造函数,07
From: https://www.cnblogs.com/wyqmx/p/17602085.html

相关文章

  • [代码随想录]Day07-字符串 part01
    题目:344.反转字符串思路:每次把最前面和最后面的交换位置即可strings库里没有反转的方法——这个反转是之后几个题的一个基础代码:双指针调换位置funcreverseString(s[]byte){l,r:=0,len(s)-1//最前面的元素,最后面的元素forl<r{s[l],s[......
  • C和C++进阶的学习笔记总结目录
    C语言–C语言基础知识积累记录学习教程:参考C++教程网之跟我一起学Cdo{…}while(0)的用途汇总(欢迎补充)在一些Linux内核和其它的开源代码中可见到【C语言】《带你学C带你飞》,笔记:链接––C++–一张图总结GoogleC++编程规范(GoogleC++StyleGuide)C++基础学习目录总结参考:链......
  • c++11 std::condition_variable
    std::condition_variable需要配合unique_lock使用,wait(unique_lock<mutex>&)notify_one()调用时,只有随机一个wait()线程会得到通知notify_all(),所有wait()线程会被通知并得到执行wait()调用会阻塞当前线程wait()线程中用到的unique_lock不会阻塞notify线程中的锁//condit......
  • 3.C++中NULL和nullptr区别
    3.C++中NULL和nullptr区别1.NULL是什么在《NULL,0,'\0',"0","\0"的区别》一文中,我们已经知道了在C中NULL是什么,在C的头文件中,通常定义如下:#defineNULL((void*)0)但是在C++中,它是这样定义的:#defineNULL0可以在stddef.h看到完整的这段:#undefNULL#ifdefined(__cplusp......
  • 2.简要说明C++的内存分区
    2.简要说明C++的内存分区1.一个由C/C++编译的程序占用的内存分为以下几个部分:C++中的内存分区,分别是堆、栈、自由存储区、全局/静态存储区、常量存储区和代码区。如下图所示栈:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈......
  • 4.可以说一下你了解的C++得内存管理吗?
    4.可以说一下你了解的C++得内存管理吗?1.一个由c/C++编译的程序占用的内存分为以下几个部分:C++中的内存分区,分别是堆、栈、自由存储区、全局/静态存储区、常量存储区和代码区。如下图所示栈:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自......
  • 5.C++中类的数据成员和成员函数内存分布情况
    5.C++中类的数据成员和成员函数内存分布情况非静态成员的数据类型大小之和。编译器加入的额外成员变量(如指向虚函数表的指针)。为了边缘对齐优化加入的padding。空类(无非静态数据成员)的对象的size为1,当作为基类时,size为0。C++类是由结构体发展得来的,所以他们的成员变......
  • 128.用C语言实现C++的继承
    128.用C语言实现C++的继承#include<iostream>usingnamespacestd;//C++中的继承与多态structA{virtualvoidfun()//C++中的多态:通过虚函数实现{cout<<"A:fun()"<<endl;}inta;};structB:publicA//C++中的继承:B类公有继......
  • c++控制台时钟显示时间
    在旧电脑上刷了ubuntu的服务器版本,开着的时候旧电脑(yoga)的屏幕就处于了无用的状态。为了更好的利用这个屏幕,简单使用c++写了一个显示时间的代码。由于这台yoga的屏幕是可以360翻转的,所以给时间的显示也增加了一点翻转功能。1#include<iostream>2#include<ctime>3#......
  • Java学习Day07
    第六章方法一、方法1.1、概述在我们的日常生活中,方法可以理解为要做某件事情,而采取的解决办法。如:小明同学在路边准备坐车来学校学习。这就面临着一件事情(坐车到学校这件事情)需要解决,解决办法呢?可采用坐公交车或坐出租车的方式来学校,那么,这种解决某件事情的办法,我们就称为方......