面向对象基础-析构函数-this-static-const

析构函数

析构函数是与构造函数对立的函数。

构造函数

析构函数

创建对象时手动调用

当对象销毁时,自动调用

函数名称与类名相同

函数名称是~类名

构造函数可以重载

析构函数没有参数,不能重载

用于创建对象时并初始化

用于销毁对象时释放资源

“有构造函数返回值”

没有返回值

3.4.3的代码优化为:

#include <iostream>
#include <string.h>
using namespace std;
class Dog
{
private:
    char *name;
public:
    Dog(char *n)
    {
        name = new char[20];
        strcpy(name,n);
    }

    Dog(Dog &d)
    {
       name = new char[20];
       strcpy(name,d.name);
    }

    void show_name()
    {
        cout << name << endl;
    }
    // 析构函数,对象销毁时自动调用(花括号结束对象销毁)
    ~Dog()
    {
        cout << "我被调用了" << endl;
        delete []name;
        name = NULL;
    }
};
int main()
{
    char arr[20] = "旺财";
    Dog d1(arr);
    Dog d2(d1); // 拷贝构造函数
    strcpy(arr,"大黄");
    d1.show_name(); // 旺财
    d2.show_name(); // 旺财
    return 0;
}

  1. 作用域限定符“::”

匿名空间:默认空间

名字空间:用户命名

就近原则;

1 名字空间(熟悉)

#include <iostream>
using namespace std;//匿名空间
int a = 2;
namespace my_space//名字空间
{
    int a = 3;
    int b = 4;
}
using namespace my_space;//使用名字空间
int main()
{
    int a = 1;
    std::cout << a << std::endl;  // 1 就近原则
    std::cout << ::<< std::endl; // ::是匿名名字空间。2,匿名空间为空会报错
    cout << my_space::<< endl; // 3 名字空间
    cout << b << endl;  // 4若没有其他匿名或就近,则直接调用唯一空间变量若有其他空间变量,则需要指定空间
    return 0;
}

2 类内声明,类外定义,主函数内调用

#include <iostream>
using namespace std;
class Demo
{
public:
    Demo();//构造函数类内声明
    void test(string str);//类内声明函数
};
//类外实现
Demo::Demo()
{
    cout<<"创建了一个对象"<<endl;
}
//类外实现
void Demo::test(string str)
{
    cout<<str<<endl;
}
int main()
{
    Demo d;//创建一个类的对象
    d.test("helloworld ");//调用类内成员函数
    return 0;
}

this指针

1 概念

this指针是一个特殊指针,指向当前类对象的首地址。

成员函数(包括构造函数与析构函数)都有this指针。因此this指针只能在类内使用。实际上this指针指向的就是当前运行的成员函数所绑定的对象。

#include <iostream>
#include <string.h>
using namespace std;
class Test
{
private:
    string name;
public:
    Test(string name):name(name){}
    void show_this()
    {
        cout << this << endl; // 0x61fe84
    }
};
int main()
{
    Test t1("小明");
    cout << &t1 << endl; // 0x61fe84
    t1.show_this();
    Test *t2 = new Test("张三");
    cout << t2 << endl;
    t2->show_this(); // 0x1327a8
    delete t2;
    t2 = NULL;
    return 0;
}

指针地址一致

  • 类中成员的调用都依赖this指针,通常由编译器自动添加。

#include <iostream>
#include <string.h>
using namespace std;
class Test
{
private:
    string name;
public:
    Test(string name):name(name){}
    void func1()
    {
        cout << "哈哈哈哈" << endl;
    }
    void func2()
    {
        // 类内调用成员时,编译器自动添加this指针。
        cout << this->name << endl;
        this->func1();
    }
};
int main()
{
    Test *t2 = new Test("张三");
    cout << t2 << endl;
    t2->func2();
    delete t2;
    t2 = NULL;
    return 0;
}

2 功能

  • 区分重名的局部变量与成员变量

#include <iostream>
using namespace std;
class Test
{
private:
    string name;
public:
    Test(string name)
    {
        this->name = name;//指示当前类的成员对象
    }

    void test_this()
    {
        cout << this << endl; // 0x61fe84
    }
};
int main()
{
    Test t1("小明");
    cout << &t1 << endl; // 0x61fe84
    t1.test_this();
    Test *t2 = new Test("张三");
    cout << t2 << endl; // 0xf726a8
    t2->test_this();
    return 0;
}

  • 类中成员的调用都依赖于this指针,通常由编译器自动添加。

#include <iostream>
using namespace std;
class Test
{
private:
    string name;
public:
    Test(string name)
    {
        this->name = name;
    }
    void func1()
    {
        cout << "哈哈哈哈哈" <<endl;
    }
    void func2()
    {
//        cout << this->name << endl; // this指针编译器帮我们自动添加
//        this->func1();
    }
};
int main()
{
    Test t1("小明");
    t1.func2();
    return 0;
}

  • 链式调用

支持链式调用的成员函数特点:

  1. 返回值时当前类的引用。
  2. return 后面是*this

#include <iostream>
#include <string.h>
using namespace std;
class Test
{
private:
    int val = 0;
public:
    Test &add(int i)
    {
        val += i;   // val = val + i;
        return *this;//返回类对象
    }
    int get_val()
    {
        return val;
    }
};
int main()
{
    Test t1;
    t1.add(1);
    t1.add(2);
    t1.add(100);
    cout << t1.get_val() << endl;
    // 链式调用
    Test t2;
    cout << t2.add(2).add(21).add(300).add(221).get_val() << endl;
    return 0;
}

static 关键字

1 静态局部变量

使用static修饰局部变量,这样的变量就是静态局部变量。

静态局部变量在第一次调用的时候创建,指导程序结束后销毁,同一个类的所有对象共用这一份静态局部变量。

#include <iostream>
using namespace std;
class Test
{
public:
    void func()
    {
        int a = 1;
        static int b = 1;
        cout << "a=" << ++<< " " << &<< endl;
        cout << "b=" << ++<< " " << &<< endl;
    }

};
int main()
{
    Test t1;
    t1.func(); // 2,2
    t1.func();

    Test t2;
    t2.func();

    Test t3;
    t3.func();

    return 0;
}

注意:a可能会在同一个内存地址,反复销毁创建。

2 静态成员变量

使用static修饰成员变量,这样的变量就是静态成员变量。

静态成员变量需要在类内声明,类外初始化。

一个类的所有对象共用一份静态成员变量,虽然静态成员变量可以使用对象调用,但是更建议直接使用类名调用。所以静态成员变量可以脱离对象使用(非静态成员无法直接通过类名调用),在程序开始运行时就开辟内存空间,直到程序运行结束销毁。

更推荐使用类名直接进行调用。代码的可读性更好

#include <iostream>
using namespace std;
class Test
{
public:
    int a = 1;
//    static int b = 2; // 错误,静态成员变量需要类内声明,类外初始化
    static int b;
};
int Test::= 2;
int main()
{
    cout << Test::<< " " << &Test::<< endl;//静态成员变量可以通过类名直接调用,脱离对象使用。
    Test t1;
    cout << t1.a++ << " " << &t1.<< endl;
    cout << t1.b++ << " " << &t1.<< endl;
    cout << t1.a++ << " " << &t1.<< endl;
    cout << t1.b++ << " " << &t1.<< endl;

    cout << "----------------" << endl;

    Test t2;
    cout << t2.a++ << " " << &t2.<< endl;
    cout << t2.b++ << " " << &t2.<< endl;
    cout << Test::<< " " << &Test::<< endl;
    return 0;
}

3 静态成员函数

使用static修饰成员函数,这样的函数就是静态成员函数。

与静态成员变量相似的有:

  • 都可以通过类名直接使用,也可以通过对象调用(建议使用类名直接调用)。
  • 可以脱离对象使用

静态成员函数没有this指针,不能在静态成员函数中调用同类中的其他非静态成员函数,但是静态成员函数,可以调用静态成员函数。

#include <iostream>
using namespace std;
class Test
{
public:
    void func0()
    {
        func1();
        cout <<"非静态成员函数0"<<endl;
    }
    static void func1()
    {
        cout <<"静态成员函数1"<<endl;
    }
    static void func2()
    {
//        func0();//静态成员函数没有this指针,不能在静态成员函数中调用同类中的其他非静态成员函数,
        func1();//但是静态成员函数,可以调用静态成员函数。
        cout <<"静态成员函数2"<<endl;
    }
};
int main()
{
    Test::func1();
    Test t1;
    t1.func0();
    t1.func1();
    t1.func2();
    return 0;
}

【思考】我如果想在静态成员函数里,调用非静态成员函数,应该怎么做?

  • 可以通过参数将对象传进来,因为静态成员函数没有this指针,例如:

#include <iostream>
using namespace std;
class Test
{
public:
    void func0()
    {
        func1();
        cout <<"非静态成员函数0"<<endl;
    }
    static void func1()
    {
        cout <<"静态成员函数1"<<endl;
    }
    static void func2(Test &t)
    {
        t.func0();
//静态成员函数没有this指针,不能在静态成员函数中调用同类中的其他非静态成员函数,
        func1();//但是静态成员函数,可以调用静态成员函数。
        cout <<"静态成员函数2"<<endl;
    }
};
int main()
{
    Test::func1();
    Test t1;
    t1.func0();
    t1.func1();
    t1.func2(t1);
    return 0;
}

const关键字

1 const修饰成员函数

const修饰的成员函数,表示常成员函数,特性如下:

  • 可以调用成员变量,但是不能修改成员变量的值。
  • 不能调用非const修饰的成员函数,哪怕这个函数并没有修改成员变量。(const修饰的成员函数,不能调用非const 修饰的成员函数,只能调用const修饰的成员函数

建议只要成员函数不修改变量,就使用const修饰,例如:get、show等函数。

#include <iostream>
using namespace std;
class Demo
{
private:
    int a;
public:
    Demo(int a)
    {
        this->a = a;
    }
    void func()
    {
        cout << "哈哈哈哈" << endl;
    }
    int get_demo() const
    {
        return a;
    }
    void test() const
    {
//        a++; // 错误 const修饰的成员函数,不能修改成员变量
        cout << a << endl;
//        func(); 错误 const修饰的成员函数,不能调用非const 修饰的成员函数,只能调用const修饰的成员函数
        cout << get_demo() << endl;

        int i = 1;
        i++;
        cout << i << endl;
    }
};
int main()
{
    Demo demo(1);
    cout << demo.get_demo() << endl;
    demo.func();
    demo.test();
    return 0;
}

2 const修饰对象

const修饰的对象被称为常量对象,这种对象的成员变量值无法被修改,也无法调用非const的成员函数。

#include <iostream>
using namespace std;
class Demo
{
private:
    int a;
public:
    int b = 20;
    Demo(int a)
    {
        this->a = a;
    }

    void func()
    {
        cout << "哈哈哈哈" << endl;
    }

    int get_demo() const
    {
        return a;
    }

    void test() const
    {
//        a++; // 错误 const修饰的成员函数,不能修改成员变量
        cout << a << endl;
//        func(); 错误 const修饰的成员函数,不能调用非const 修饰的成员函数
        cout << get_demo() << endl;

        int i = 1;
        i++;
        cout << i << endl;
    }
};
int main()
{
//    const Demo demo(1);
    Demo const demo(1); // 两种初始化方式,等效于上一行
    cout <<demo.get_demo() << endl;

//    demo.func(); // 错误 const修饰的对象,无法调用非const的成员函数
    demo.test();
//    demo.b++; // 错误const修饰的对象,无法修改成员变量
    cout << demo.b << endl; // 可以调用,但是不能修改
    return 0;
}

3 const修饰成员变量

cosnt修饰的成员变量称为常成员变量,表示该成员变量的值无法被改变。

常成员变量有两种初始化的方式:

  • 直接赋值
  • 声明后赋值、使用构造初始化列表

两种方式一块使用时,前者失效,后者为准。

#include <iostream>
using namespace std;
class Demo
{
private:
    const int a = 1;
    const int b = 2;
    const int c = 3;//初始化赋值
public:
    Demo(int a,int b,int c):a(a),b(b),c(c){}//构造初始化列表赋值
    void show()
    {
        cout << a << " " << b << " " << c << endl;
    }
    void test()
    {
        //        a++; // 错误,const修饰的成员变量,无法被改变
        //        b++;
        //        c++;
        cout<<"const修饰的成员变量,无法被改变"<<endl;
    }
};
int main()
{
    Demo demo(10,20,30);
    demo.test();
    demo.show();
    return 0;
}

4 const修饰局部变量

const修饰局部变量,表示该局部变量不可被修改。

这种方式常用于引用参数

#include <iostream>
#include <string.h>
using namespace std;

class Demo
{
private:
    const int a = 1;
    const int b = 2;
    const int c = 3;

public:
    // 构造初始化列表
    Demo(int a,int b,int c):a(a),b(b),c(c){}

    void show()
    {
        cout << a << " " << b <<" "<< c << endl;
    }
    void test()
    {
        const int d = 10;
//        d = 20;   // 错误,const修饰的局部变量,无法被修改。
        cout << d << endl;
    }

};

int main()
{
    Demo d(10,20,30);
    d.show();   // 以列表为准
    d.test();
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/285404.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

webRTC实时通信demo

参考文档&#xff1a; https://www.jianshu.com/p/f439ce5cc0be https://www.w3cschool.cn/socket demo流程示意图&#xff08;用户A向用户B推送视频&#xff09;&#xff1a; #mermaid-svg-0KZaDQ5DBl28zjmZ {font-family:"trebuchet ms",verdana,arial,sans-seri…

影视后期:PR 调色处理,灰片还原,校色偏色素材

灰片还原 确定拍摄灰片的相机型号品牌官网下载专用log文件LUT-浏览-导入slog3分析亮部波形-增加画面对比分析矢量示波器-提高整体饱和 校正LUT可以将前期拍摄的log色彩模式的视频转换为成709色彩模式&#xff0c;即将灰度视频转换为正常效果(灰片还原) 各个相机有对应的校正L…

链路层、网络层、传输层、应用层长度

参考&#xff1a;链路层、网络层、传输层、应用层长度 链接&#xff1a;https://blog.csdn.net/qq_41658597/article/details/120683870 目录 1、概述2、TCP、UDP数据包最大值的确定3、TCP、UDP数据包最小值的确定4、实际应用IP层 1、概述 首先要看TCP/IP协议&#xff0c;涉及到…

PyTorch中常用的工具(4)Visdom

文章目录 前言3.2 Visdom 前言 在训练神经网络的过程中需要用到很多的工具&#xff0c;最重要的是数据处理、可视化和GPU加速。本章主要介绍PyTorch在这些方面常用的工具模块&#xff0c;合理使用这些工具可以极大地提高编程效率。 由于内容较多&#xff0c;本文分成了五篇文…

李宏毅机器学习第二十三周周报 Flow-based model

文章目录 week 23 Flow-based model摘要Abstract一、李宏毅机器学习1.引言2.数学背景2.1Jacobian2.2Determinant2.3Change of Variable Theorem 3.Flow-based Model4.GLOW 二、文献阅读1. 题目2. abstract3. 网络架构3.1 change of variable formula3.2 Coupling layers3.3Prop…

http——https实现指南

第一部分&#xff1a;HTTPS安全证书简介 什么是HTTPS安全证书&#xff1f; 在网络通信中&#xff0c;HTTPS安全证书是一种由可信任的证书颁发机构&#xff08;CA&#xff09;签发的数字证书&#xff0c;用于保障网站与用户之间的数据传输安全。通过加密和身份验证&#xff0c…

nginx安装和配置

目录 1.安装 2.配置 3.最小配置说明 4. nginx 默认访问路径 1.安装 使用 epel 源安装 先安装 yum 的扩展包 yum install epel-release -y 再安装 nginx yum install nginx -y 在启动nginx 前先关闭防火墙 systemctl stop firewalld 取消防火墙开机自启 systemctl di…

idea中java maven程序打JAR包的方式

JAR包是一种文件格式&#xff0c;用于将Java类、资源和元数据打包到一个文件中。它通常用于将Java库、应用程序或模块分发给其他开发人员或部署到不同的环境中。JAR包可以包含许多不同类型的文件&#xff0c;包括.class文件&#xff08;编译后的Java类&#xff09;、.java文件&…

oracle-SCN系统改变号

SCN system change number 我们看到的SCN是一串数字&#xff0c;由时间经过函数算出的&#xff0c;其实就是时间。但时间的比较复杂&#xff0c;不如转换成数字比较。 给一个日志加scn号&#xff0c;其实就是给日志加上时间点。 2常见的SCN 对于scn的理解 控制文件中有两个sc…

TDD-LTE TAU流程

目录 1. TAU成功流程 1.1 空闲态TAU 1.2 连接态TAU 2. TAU失败流程 当UE进入一个小区&#xff0c;该小区所属TAI不在UE保存的TAI list内时&#xff0c;UE发起正常TAU流程&#xff0c;分为IDLE和CONNECTED&#xff08;即切换时&#xff09;下。如果TAU accept分配了一个新的…

HarmonyOS应用开发-搭建开发环境

本文介绍如何搭建 HarmonyOS 应用的开发环境&#xff0c;介绍下载安装 DevEco Studio 开发工具和 SDK 的详细流程。华为鸿蒙 DevEco Studio 是面向全场景的一站式集成开发环境&#xff0c;面向全场景多设备&#xff0c;提供一站式的分布式应用开发平台&#xff0c;支持分布式多…

【起草】【第十二章】定制ChatGPT数字亲人

身为普普通通的我们&#xff0c;不知道亲人们在哪一天就要离开这个世界 &#xff1f; 作为普普通通的程序员&#xff0c;我们可以为我们的亲人做点什么 &#xff1f; 让他们以数字资产形式留在人世间 ? 对话&#xff5c;6岁女孩病逝捐器官&#xff0c;妈妈&#xff1a;她去…

js中的数组使用及常见属性方法

目录 数组概念 数组创建方法 数组的length属性 数组的遍历的使用 JavaScript 常用数组方法 concat typeof split length charAt indexOf substring push pop join 数组概念 数组对象的作用是&#xff1a;使用单独的变量名来存储一系列的值。 数组创建方法 构造函…

Matplotlib_4.文字图例尽眉目

文章目录 一、Figure和Axes上的文本1.text2.title和set_title3.figtext和text4.suptitle5.xlabel和ylabel6.annotate7.字体的属性设置 二、Tick上的文本1.简单模式2.Tick Locators and Formatters 三、legend&#xff08;图例&#xff09; 一、Figure和Axes上的文本 Matplotli…

面试官:说说JVM内存整体结构?

Java JVM内存结构的面试常问知识 说说JVM内存整体的结构&#xff1f;线程私有还是共享的&#xff1f; JVM 整体架构&#xff0c;中间部分就是 Java 虚拟机定义的各种运行时数据区域。 ​ Java 虚拟机定义了若干种程序运行期间会使用到的运行时数据区&#xff0c;其中有一些会…

《深入理解Java虚拟机(第三版)》读书笔记:Java内存区域与内存溢出异常、垃圾收集器与内存分配策略

下文是阅读《深入理解Java虚拟机&#xff08;第3版&#xff09;》这本书的读书笔记&#xff0c;如有侵权&#xff0c;请联系删除。 文章目录 第2章 Java内存区域与内存溢出异常2.2 运行时数据区域2.3 HotSpot虚拟机对象探秘 第3章 垃圾收集器与内存分配策略3.2 对象已死&…

网络安全专家 Mikko Hyppönen 对 2024 年的五大 AI 网络威胁发出警告

在网络安全前线战斗了数十年的 Mikko Hyppnen&#xff0c;这位 54 岁的专家最近在一次视频通话中向 TNW 透露了他对 2024 年最令人担忧的五大人工智能&#xff08;AI&#xff09;网络威胁。这些威胁并没有特定的顺序&#xff0c;尽管其中有一个是导致他最为失眠的。 深度伪造&a…

HarmonyOS官网案例解析——保存应用数据

介绍 本篇Codelab将介绍如何使用基础组件Slider&#xff0c;通过拖动滑块调节应用内字体大小。要求完成以下功能&#xff1a; 实现两个页面的UX&#xff1a;主页面和字体大小调节页面。拖动滑块改变字体大小系数&#xff0c;列表页和调节页面字体大小同步变化。往右拖动滑块字体…

江西速欣商务咨询有限公司:债务规划重组的专业法务咨询服务

在财务管理中&#xff0c;债务问题往往成为个人和企业面临的一项重要挑战。江西速欣商务咨询有限公司作为债务问题的专业解决者&#xff0c;致力于为客户提供高效而专业的债务规划重组法务咨询服务&#xff0c;帮助他们摆脱负担&#xff0c;重整财务秩序。 深谙债务规划的专业智…

通信基站绿色低碳服务认证

据标准编制组代表汇报该标准是在2022年工信部等7部门印发《信息通信行业绿色低碳发展行动计划&#xff08;2022-2025&#xff09;》提出通信基站要向集约化布局、高效化设计、绿色化建设、低碳化技术、智能化运维方向发展。加快形成以管理制度为引领、以绿色采购为关键、以评估…
最新文章