第006课 C++ 构造函数_析构函数_拷贝构造函数

顶会新宠!Gate+Attention创新思路发A会 性能提升:在Places2自然场景和CelebA-HQ人脸数据集上,与以往方法相比,该系统在自由形式掩码修复任务中取得了更高的质量和更低的误差(例如,平均ℓ1误差和ℓ2误差显著降低)。硬件效率提升:Griffin和Hawk在TPU-v3上的训练效率与Transformer相当,且在推理时具有更低的延迟和显著更高的吞吐量。门控卷积:提出了一种新的门控卷积机制,通过学习每个通道在每个空间位置的动态特征选择机制,解决了传统卷积将所有输入像素视为有效像素的问题。 阅读详情

一、构造函数:

    构造函数和析构函数是在类体中说明的两种特殊的成员函数。构造函数是在创建对象时,使用给定的值来将对象初始化。     

    析构函数的功能正好相反,是在系统释放对象前,对对象做一些善后工作。构造函数可以带参数、可以重载,同时没有返回值。     

    构造函数是类的成员函数,系统约定构造函数名必须与类名相同。构造函数提供了初始化对象的一种简单的方法。

例:

#include <iostream>
using namespace std;

class Test //类
{
    int x, y;
public:
    Test(int a, int b)//构造函数,带参数
    {
        x = a;
        y = b;
        cout << " x=" << x << ", y=" << y << endl;
    }
    int sum_xy()
    {
        return x + y;
    }
};

int main()
{
    Test test1(56,70);//只要程序运行,系统自动会初始化构造函数(自己会匹配找到带有两个参数的构造函数)
    cout << " x+y=" << test1.sum_xy() << endl;
    return 0;
}

输出结果:

【对构造函数,说明以下几点】:

1.构造函数的函数名必须与类名相同。构造函数的主要作用是完成初始化对象的数据成员以及其它的初始化工作。

2. 在定义构造函数时,不能指定函数返回值的类型,也不能指定为void类型。

3. 一个类可以定义若干个构造函数。当定义多个构造函数时,必须满足函数重载的原则。

4.构造函数可以指定参数的缺省值。

5.若定义的类要说明该类的对象时,构造函数必须是公有的成员函数。如果定义的类仅用于派生其它类时,则可将构造函数定义为保护的成员函数。     

     由于构造函数属于类的成员函数,它对私有数据成员、保护的数据成员和公有的数据成员均能进行初始化。 

例: 

#include <iostream>
using namespace std;

class Test //类
{
    int x, y;
public:
    Test(int a, int b)//构造函数,带参数
    {
        x = a;
        y = b;
        cout << " x=" << x << ", y=" << y << endl;
    }
    Test(int a)//满足函数重载
    {
        cout << " a=" << a << endl;
    }
};

int main()
{
    Test test1(56,70);//只要程序运行,系统自动会初始化构造函数(自己会匹配找到带有两个参数的构造函数)
    Test test2(3000);//
    return 0;
}

 输出结果:

对局部对象,静态对象,全局对象的初始化:

1)对于局部对象,每次定义对象时,都要调用构造函数。

2)对于静态对象,是在首次定义对象时,调用构造函数的,且由于对象一直存在,只调用一次构造函数。     

3)对于全局对象,是在main函数执行之前调用构造函数的。 

 例:

#include <iostream>
using namespace std;

class Test //类
{
    int x, y;
public:
    Test(int a, int b)//构造函数,带参数
    {
        x = a;
        y = b;
        cout << " 初始化局部对象"  << endl;
    }
    Test(int a)
    {
        x = a;
        y = 0;
        cout << " 初始化全局对象"  << endl;
    }
    Test()
    {
        x = 0;
        y = 0;
        cout << " 初始化静态局部对象" << endl;
    }
};

Test test2(3000);//定义全局对象

void FuncTest()
{
    cout << " 程序开始进入FuncTest()函数" << endl;
    Test test3(15, 20);//定义局部对象
    static Test test4;//定义局部静态变量  // 尾部 不能加()
}

int main()
{
    cout << " 程序开始执行 --> main()函数" << endl;
    Test test1(56,70);//定义局部对象
    FuncTest();
    return 0;
}

 输出结果:

 【缺省的构造函数】

     在定义类时,若没有定义类的构造函数,则编译器自动产生一个缺省的构造函数,

  其格式为: className::className() {  }    缺省的构造函数并不对所产生对象的数据成员赋初值;即新产生对象的数据成员的值是不确定的。

【关于缺省的构造函数】,说明以下几点:

1、在定义类时,只要显式定义了一个类的构造函数,则编译器就不产生缺省的构造函数。     

2、所有的对象在定义时,必须调用构造函数     不存在没有构造函数的对象!     

3、在类中,若定义了没有参数的构造函数,或各参数均有缺省值的构造函数也称为缺省的构造函数,缺省的构造函数只能有一个。     

4、产生对象时,系统必定要调用构造函数。所以任一对象的构造函数必须唯一。

【构造函数与new运算符】     

      可以使用new运算符来动态地建立对象。建立时要自动调用构造函数,以便完成初始化对象的数据成员。最后返回这个动态对象的起始地址。     

     用new运算符产生的动态对象,在不再使用这种对象时,必须用delete运算符来释放对象所占用的存储空间。     

     用new建立类的对象时,可以使用参数初始化动态空间。

例: 

#include <iostream>
using namespace std;

class Test //类
{
    int x, y;
public:
    Test(int a, int b)//带参数的构造函数
    {
        x = a;
        y = b;
        cout << "  调用带参构造函数"  << endl;
    }
    Test()//缺省的构造函数
    {
        x = 0;
        y = 0;
        cout << "  调用缺省构造函数" << endl;
    }
    void disp_xy()
    {
        cout << " x=" << x  << ", y=" << y << endl ;
    }
};

int main()
{
    Test *pt1, *pt2;//创建两个对象指针

    pt1 = new Test; //用new动态开辟存储空间,调用缺省构造函数
    pt2 = new Test(200, 800);//用new动态开辟存储空间,调用带参构造函数

    pt1->disp_xy();
    pt2->disp_xy();

    delete pt1;//用delete释放动态开辟的存储空间
    delete pt2;

    return 0;
}

 输出结果:

 二、析构函数:

       析构函数的作用与构造函数正好相反,是在对象的生命期结束时,释放系统为对象所分配的空间,即要撤消一个对象。

     析构函数也是类的成员函数,定义析构函数的格式为:

ClassName::~ClassName( )
{
  	......
    //  函数体;
}

例: 

#include <iostream>
using namespace std;

class Test //类
{
    double x, y;
public:
    Test(double a, double b)//带参数的构造函数
    {
        x = a;
        y = b;
        cout << "  调用带参的构造函数" << endl;
    }
    Test()//缺省的构造函数
    {
        x = 0;
        y = 0;
        cout << "  调用缺省的构造函数" << endl;
    }
    ~Test()//析构函数
    {
        cout << "  调用析构函数" << endl;
    }
};

int main()
{
    Test pt1;//创建三个对象
    Test pt2(5.6,70.8);
    Test pt3(10, 20);

    return 0;
}

 输出结果:

 【析构函数的特点如下】:     

1、析构函数是成员函数,函数体可写在类体内,也可写在类体外。     

2、析构函数是一个特殊的成员函数,函数名必须与类名相同,并在其前面加上字符“~”,以便和构造函数名相区别。     

3、析构函数不能带有任何参数,不能有返回值,不指定函数类型。     

4、一个类中,只能定义一个析构函数,析构函数不允许重载。     

5、析构函数是在撤消对象时由系统自动调用的。     

    在程序的执行过程中,当遇到某一对象的生存期结束时,系统自动调用析构函数,然后再收回为对象分配的存储空间。

    在程序的执行过程中,对象如果用new运算符开辟了空间,则在类中应该定义一个析构函数,并在析构函数中使用delete删除由new分配的内存空间。因为在撤消对象时,系统自动收回为对象所分配的存储空间,而不能自动收回由new分配的动态存储空间。

【缺省的析构函数】     

     若在类的定义中没有显式地定义析构函数时,则编译器自动地产生一个缺省的析构函数,其格式为: ClassName::~ClassName() { };     任何对象都必须有构造函数和析构函数,但在撤消对象时,要释放对象的数据成员用new运算符分配的动态空间时,必须显式地定义析构函数。

例: 

#include <iostream>
using namespace std;

class Test //类
{
    int *px;
public:
    Test()//缺省的构造函数
    {
        cout << "  调用构造函数Test::Test()" << endl;
        px = new int(1000);
        cout << " *px=" << *px << endl;
    }
    ~Test()//析构函数
    {
        delete px;
        cout << "  调用析构函数~Test::Test()" << endl;
    }
};

int main()
{
    //Test pt1;//创建对象,用完释放对象
    Test *pt1 = new Test;
    Test* pt2 = (Test*)malloc(sizeof(Test));

    delete pt1; //动态释放 归还堆的空间
    free(pt2);
    return 0;
}

输出结果:

 【实现类型转换的构造函数】     

     同类型的对象可以相互赋值,相当于类中的数据成员相互赋值;     

     如果直接将数据赋给对象,所赋入的数据需要强制类型转换,这种转换需要调用构造函数。

例: 

#include <iostream>
using namespace std;

class Test //类
{
    double x,y;
public:
    Test(double a,double b)//构造函数
    {
        x = a;
        y = b;
        cout << "  调用带参的构造函数"  << endl;
    }
    ~Test()//析构函数
    {
        cout << "  调用析构函数" << endl;
    }
    void disp()
    {
        cout << " x=" << x << ", y=" << y << endl;
    }
};

int main()
{
    Test test1(2.4, 4.75);//创建对象,赋初值
    test1.disp();
    test1 = Test(90.7, 40);//重新给对象赋值,要数据类型转换
    test1.disp();
    return 0;
}

 输出结果:

 三、拷贝构造函数

     拷贝构造函数,又称复制构造函数,是一种特殊的构造函数,它由编译器调用来完成一些基于同一类的其他对象的构建及初始化。其形参必须是引用,但并不限制为const,一般普遍的会加上const限制。此函数经常用在函数调用时用户定义类型的值传递及返回。拷贝构造函数要调用基类的拷贝构造函数和成员函数。如果可以的话,它将用常量方式调用,另外,也可以用非常量方式调用。

    拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。

拷贝构造函数通常用于:

1)通过使用另一个同类型的对象来初始化新创建的对象;

2)复制对象把它作为参数传递给函数;

3)复制对象,并从函数返回这个对象。     

     如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。

拷贝构造函数的最常见形式如下:

classname (const classname &obj) 
{
   ......
   // 构造函数的主体
}

例: 

#include <iostream>
using namespace std;

class Test //类
{
    int* px;
public:
    Test(int a);//构造函数声明
    Test(const Test& test);//拷贝构造函数声明
    ~Test();//析构函数声明
    int get_px()
    {
        return *px;
    }
};

Test::Test(int a)//构造函数
{
    cout << "  调用构造函数" << endl;
    px = new int; //为指针分配内存空间
    *px = a;
}
Test::Test(const Test& test)//拷贝构造函数
{
    cout << "  调用拷贝构造函数 并为指针px 分配内存空间" << endl;
    px = new int;
    *px = *test.px; //拷贝值
}
Test::~Test()//析构函数定义
{
    cout << "  调用析造函数,释放动态分配的内存空间" << endl;
    delete px;
}

void dis_px(Test test)
{
    cout << "  *px =" << test.get_px() << endl;
}

int main()
{
    Test test1(3000);//创建对象
    dis_px(test1); //拷贝
    return 0;
}

输出结果:

Google Gemini 模型本地可视化 Google近期发布了Gemini模型,而且开放了Gemini Pro API,Gemini Pro 可免费使用!Gemini Pro支持全球180个国家的38种语言,目前接受文本、图片作为输入并生成文本作为输出。Gemini Pro的表现超越了其他同类模型,当前版本配备了 32K 文本上下文窗口,可免费使用,且其定价将十分有竞争力。Gemini Pro具备丰富的功能:函数调用、数据嵌入、语义检索、自定义知识嵌入以及聊天功能。 阅读详情

相关推荐

基于CubeMX与lwip的STM32轻量级HTTP服务器搭建及VSCode高效开发指南

本文详细介绍了如何在STM32单片机上,利用STM32CubeMX图形化配置工具和轻量级TCP/IP协议栈lwIP,快速搭建一个轻量级HTTP服务器。通过结合VSCode的高效代码编辑能力,提供了一套从硬件连接到动态网页交互(SSI/CGI)的完整开发指南,旨在为嵌入式设备提供零成本、跨平台的Web交互界面。

weixin_29163857的博客 582

4种构造函数

C++构造函数的使用

qq_41729472的博客 6141

双目视觉入门实战:用Matlab标定相机,再到Python OpenCV完成测距的完整链路

本文详细介绍了双目视觉技术的完整实现流程,从Matlab相机标定到Python OpenCV测距的全链路实践。重点解析了Matlab与OpenCV的参数转换技巧,以及立体校正、视差计算等关键步骤的代码实现,帮助开发者快速掌握双目测距系统的搭建方法。

weixin_29166013的博客 445

构造函数的含义和使用

构造函数大全

阿天 2651

Win11内核隔离无法打开的解决方案详解

内核隔离问题的解决需遵循"先硬件后软件"的排查原则,90%以上的案例可通过驱动清理或外设断开解决。对于必须禁用该功能的用户,建议定期使用Windows Defender进行全盘扫描,并保持系统更新至最新版本。技术决策需在安全性和兼容性之间取得平衡,本文提供的多维解决方案可帮助用户构建更稳定的Windows 11使用环境。

mmoo_python的博客 4825

开源代码分享(29)-基于拉丁超立方抽样的风光场景生成和削减

作为分层抽样方法的一 种,拉丁超立方抽样具有良好的抽样精度和效率[14]。本文使用多场景方法来描述可再生能源(风电、光伏)的不确定性。以风电功率为例,首先假定风电功率服从正态分布 N(μ, δ 2 ),μ 为预测值的期望值,δ 为其波动的百分比。接着,采用拉丁超立方抽样[21]生成大量服从概率分布约束的风电出力场景,并采用考虑 Kantorovich 距离[22]的场景削减技术处理该场景,进行场景削减。最后,导出具有相应概率的削减之后的场景。

配电网和matlab的博客 923

【JS小知识】this的指向、工厂方法、构造函数及优化、prototype原型、forEach()的使用

/** * 解析器在调用函数时,每次都会向函数内部传递一个隐含的参数 * 这个隐含的参数就是this,this指向的是一个对象, * 这个对象我们称为函数执行的上下文对象, * 根据函数的调用方式的不同,this会指向不同的对象 * 1、以函数方式调用,this是window * 2、以方法的形式调用时,this就是调用方法的那个对象 * 3、以构造函数的形式调用时,this是新创建的对象 * */ function...

因为遇见你,我,三生有幸呀 1031

【Shader】Unity批量更换Shader

在Unity开发中,因为渲染管线问题,经常会遇到需要大量更改shader的问题,本篇文章讲述批量更换Shader的工具。

憨辰 1465

构造函数详解

构造函数详解 构造函数的概念: 构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员都有一个合适的初始值,并且在对象的生命周期内只调用一次。 构造函数的特性 函数名与类名相同。 无返回值。 编译器自动调用对应的构造函数。 构造函数可以重载。 为什么要引出构造函数这一概念 看下面的代码,对于Date类,可以通过InitDate公有的方法给对象设置内容,但是如果每次创建对象都调用该方法设置信息,未免有点麻烦,那能否在对象创建时,就将信息设置进去呢? 现在我们

weixin_43831728的博客 6万+

采购订单定价策略 超详细

‘需求’字段里填写的是一个例程编号(例程是一段判断程序),如果我们在需求中维护了例程编号,那只有这个例程条件被满足时,这个条件表才会被系统自动读取。一部分的条件表只有在凭证项目满足一定的条件时才会被读取。 ‘排斥的’字段如果别勾中的话,那表明如果这个条件表被系统成功读取到数据后,系统将停止这个存取顺序的执行,否则,系统将继续执行下去。 注意:a、如果我们给某个条件类型设定了有效期的话,那我们必须给这个条件类型分配一个存取顺序。 b、不能给一个抬头条件分配存取顺序。 是...

竹大的博客 1万+

Android实战——白天黑夜模式设置

白天黑夜模式是一种动态的UI模式,根据当前时间或用户设置的偏好,在白天和黑夜之间进行切换。它通过调整应用程序的颜色、亮度和其他可视化元素来提供更加舒适和易读的用户界面。

小旭的专栏 5226

构造函数方法

对于常量成员、引用成员和没有默认构造函数的成员,必须使用这种方法。这些默认值会被所有构造函数使用,除非在构造函数中显式初始化。用于通过转移资源来创建新对象,避免不必要的拷贝。一个构造函数可以调用同一个类中的另一个构造函数。可以显式地删除构造函数,防止使用特定的构造函数。可以是任何类数据类型,关于模板就不在此多做赘述。用于在构造函数的初始化列表中初始化成员变量。构造函数也可以是模板,以允许不同类型的参数。它用于实现深拷贝,特别是当类包含指针成员。如果在运行时,该函数向外抛出了异常,没有参数的构造函数。

onetelafu的博客 2900

GPU架构(1.1)--介绍 GPU的 VPU(Vision Processing Unit)架构

基于自研的 VPU(Vision Processing Unit)架构,专为高性能图形处理和深度学习设计。VPU 架构通过优化计算单元、内存层次结构、同步机制和指令流水线,提供了卓越的性能和能效。VPU 架构通过优化计算单元、内存层次结构、同步机制和指令流水线,提供了卓越的性能和能效。这种架构不仅适用于高性能图形处理,还广泛应用于深度学习、科学计算和边缘计算等领域。通过了解 VPU 架构的详细设计和工作原理,读者可以更好地利用这些先进的 GPU 技术,开发出高效、可靠的计算系统。

MHD0815的博客 1299

0815,析构函数,拷贝构造函数,赋值运算符函数

1,用一个已经存在的同类型的对象来初始化新对象的 构造函数2,类名 (const 类名 & )3,不可以3.1 不可以去掉引用符号(遇到第二种调用时机“形参实参都是对象,用实参初始化形参”的时候,会再一次调用拷贝构造,导致递归调用3.2 不可以去掉const (1,确保右操作数的数据成员不会被改变,2,为了能够赋值临时对象的内容,非const引用不能绑定临时变量)1,用已经创建的对象给另一个对象赋值的时候,会调用赋值运算函数(没有自定义时,系统会提供一个默认版本(浅拷贝版本))

qq_51583806的博客 1013

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

C++ 拷贝构造函数练习

006:奇怪的类复制 查看 提交 统计 提问 总时间限制:  1000ms   内存限制:  65536kB // 在此处补充你的代码 描述 程序填空,使其输出9 22 5 #include &lt;iostream&gt; using namespace std; class Sample { public: int v; }; void PrintAndDou...

wwxy1995的博客 709

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

【006 类和数据的抽象】C++中空类默认产生哪些类成员函数?

【代码】【006 类和数据的抽象】C++中空类默认产生哪些类成员函数?

kashine的博客 739

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

构造函数、析构函数

C++

m0_75179090的博客 91

06奇怪的类复制【三种构造函数+拷贝构造函数与运算符重载的区别】

在我反复试验后,得出以下结论: 这两个的区别就在于: 一.赋值运算符重载 含义:将对象赋给一个已有对象。 注意:一定要是已有对象。也就是说,要这样写才会调用赋值运算符重载: Sample b; b=a; 二.拷贝构造函数 含义:创建一个新对象。 注意:一定要是新对象。也就是说,要这样写,会调用拷贝构造函数:Sample b=a; 当然,还有在参数是对象、函数返回类型是对象的情况下也会调用。 结果图:可以对比课堂笔记(Typora)看。 题目+答案: #include using namespace std

beautiful_Anne的博客 286

【C++】类和对象(3)(默认成员函数--拷贝构造&赋值重载)

拷贝构造函数是构造函数的重载,用于创建一个对象时,以另一个同类型对象作为参数,从而将参数对象的数据成员的值复制给新创建的对象。函数只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰)。

小白要加油的博客 905

006:奇怪的类复制

006:奇怪的类复制 题面 描述 程序填空,使其输出9 22 5 #include <iostream> using namespace std; class Sample { public: int v; // 在此处补充你的代码 }; void PrintAndDouble(Sample o) { cout << o.v; cout << endl; } int main() { Sample a(5); Sample b = a; PrintAndDou

ACMer_WarYan 610

006__C++类的特殊用法

006__C++类的特殊用法。分别有类的组合,多继承,棱形继承,虚基类,虚函数,虚表中的虚函数。

你好啊!猿道友 456

< C++ >:C++ 类和对象(中) - 2

目录 4、拷贝构造函数 4.1、概念 4.2、特征 5、赋值运算符重载 5.1、运算符重载 5.2、赋值运算符重载

lcc11223的博客 446

C++ #006 运算符重载 复制构造函数的调用问题 三种情况 02

#include<iostream> #include<cstdio> using namespace std; class Complex { double real; double imag; static int complexTotal; public: Complex(double setReal, double setImag); Complex(); Complex(const Complex& demo);

这是博客描述 148

【程序设计与算法(三)第8周测验(2019秋季)】006:我自己的 ostream_iterator

描述 程序填空输出指定结果 #include <iostream> #include <list> #include <string> using namespace std; template <class T1,class T2> void Copy(T1 s,T1 e, T2 x) { for(; s != e; ++s,++x) *x...

Erqi Huang的博客 812

C++面向对象程序设计 006:奇怪的类复制 ---- (北大Mooc)

原题题目 描述 程序填空,使其输出9 22 5 #include <iostream> using namespace std; class Sample { public: int v; // 在此处补充你的代码 }; void PrintAndDouble(Sample o) { cout << o.v; cout << endl; } int main() { Sample a(5); Sample b = a; PrintAndDouble(b);

Love 6's Private Blog 634

c++OOP之复制控制 ------复制构造函数、赋值重载、析构

本博文我们讨论OOP复制控制的一些内容; 首先考虑对象复制的时机: 非引用类型 1):根据一个类去显式或者隐式初始化一个对象; 2):复制一个对象,将它作为实参传给一个函数; 3):从函数返回时复制一个对象。( string tolittle(string word)) 4):初始化顺序容器中的元素。(例如vector 必须具备 copy,assignment功能) 一个空类...

weixin_30707875的博客 106
上一篇: 第005课 C++ 类与对象(三)
下一篇: 第007课 C++ 友元与动态内存
W_Linux220
博客等级 码龄3年 116粉丝 17原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值