this指针—静态成员—单例模式

01 this指针

C++是在C语言的基础上发展而来的,第一个C++的编译器实际上是将C++程序翻译为C语言,然后再使用C语言编译器编译

C语言中没有类的概念,只有结构,函数都是全局函数,没有成员函数的概念

翻译的时候,将class变成struct,对象翻译为结构体变量是显而易见的,但是对于类的成员函数该如何翻译呢?对于 t1.show() 这样通过一个对象调用成员函数的语句,又应该如何翻译呢?


C语言只有全局函数,最开始的时候,成员函数都是被翻译为全局函数,对于 t1.show() 这样通过一个对象调用成员函数的语句也只能翻译为全局函数的调用。此时产生了一个问题,如何让翻译之后的show函数还能作用于 t1 这个对象呢?

        解决方法:

                t1.show();  ------> show(&t1);

                t2.show();  ------> show(&t2);
        

        偷偷的给函数传递一个参数,把调用者对象(t1)的地址作为参数传入函数的内部(实参)

        在函数内部就可以通过这个地址访问这个调用者对象的属性

        

        并且这个地址的形参名就是 this (不是程序员定义的,而是编译器加的)

                void show();

                ======>

                void show(Test *const this) {}

        所有的非静态成员函数中都可以使用 this 指针,this指针指向了调用这个函数的那一个对象的地址

        可以通过gdb验证


为什么需要 this 指针?

        为了让函数能够区分不同的调用对象,C++编译器在每一个非静态成员函数中都隐藏了一个this指针,这个指针保存的是当前调用者的地址(让操作和对象能够绑定在一起)

        构造函数中的this表示正在初始化的对象的地址

        析构函数中的this表示正在销毁的对象的地址


this指针的作用域是在类成员函数的内部(因为是一个形式参数)当类的非静态成员函数访问类的成员变量时,编译器将对象自己本身的地址作为一个隐藏的参数传递给函数


为什么在成员函数中(t1.show())可以访问调用者对象(t1)的成员属性呢?

        就是因为有this指针
        在成员函数中,对类成员变量的访问,其实都是对this的隐式使用


在C++中,使用类类型创建的对象,每一个对象都有自己的地址空间,该空间中存储的是对象的非static成员变量,不存储成员函数,所有同类的对象,共享成员函数

        所以,在计算对象所占用的空间大小时,不需要考虑成员函数
        只需要考虑非static成员变量即可(考虑对齐,参考结构体中的内容)

 一个对象的this指针会影响对象的大小吗?
        不会,this不是对象的成员,是成员函数的形式参数,不影响sizeof的结果

this指针可以改变指向吗?
        不行
        void show();
        ------>
        void show(
Test * const this)


        const修饰的函数是一个常函数,不能修改对象数据
        

        int a;

        int *p = &a; // YES

        const int *p = &a; // YES

        const int b;

        int *q = &b; // ERROR,权限只能降,不能升

        const int *q = &b; // YES


        void show();  -----> void show(Test *const this);

        上面的this只能指向非常量对象,不能指向常量对象

                Test t1{100};

                t1.show(); // YES    Test *const this = &t1;

                const Test t2{100};

                t2.show(); // ERROR  Test *const this = &t2; // 两边的类型不一致

                        // Test * cosnt this     const  Test *  // 权限只能降,不能升
                        // Test * const this  // 不可以改变指向,可以修改this指向的对象的值

                        // const Test * // 可以改变指向,不可以修改this指向的对象的值

                        // 指向:可以 ——> 不可以,降权限        

                        // this指向的对象的值:不可以 ——> 可以,升权限


        void show() const; ------> void show(const Test * const this);

        上面的this既可以指向常量对象,又可以指向非常量对象

                Test t1{100};

                t1.show(); // YES  // const Test *const this = &t1;  // 降权限

                const Test t2{100};

                t2.show(); // YES  // const Test * const this = &t2; // 两边的类型一致

                        // const Test * const this     const Test *

给程序员的表现就是常量对象只能调用常函数,但是非常量对象,既可以调用常函数,又可以调用非const函数,权限只能降,不能升
       
const修饰一个函数,实际上const是修饰了函数的this指针

02 静态成员

需求:在项目的运行过程中,需要统计某一种类型的对象的数量


思路:

        1. 使用一个专门的变量(count)来保存对象的数量

        2. 在对象创建的时候(构造函数中),给count+1,在对象销毁的时候(析构函数中),count-1

        3. 当需要查看对象的数量的时候,只需要直接读取count的值即可

        ========>

        count 应该是一个全局变量......

       

成员变量可不可以?

        不行,因为这个变量需要有"共享"性,不能是单独的属于某一个对象


但是全局变量的数据非常的不安全,最终可能无法保证结果的正确性

需要一个变量,能够在所有同类型的对象之间实现数据共享,同时又能够保证数据的安全性

======>

        就可以使用静态成员(静态成员变量)

(1) 静态成员变量

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

        

        特点:

                static成员变量不属于某一个特定的对象,而是属于整个类,是类的一部分,该类的所有对象共享静态成员

                静态成员变量使用前必须初始化,而且必须在类外初始化,不能在类内初始化,且只能在全局初始化

        格式:

                类型  类名::静态成员变量名 = 初始值;

        
       
不影响 类类型 和 对象 的大小(sizeof):

                静态成员变量,只有唯一的一份副本,而其他的非静态成员变量,有多少个对象就有多少份副本(每一个对象中都有自己的数据)

                ======>

                sizeof(类名) and sizeof(对象名):不算静态成员变量的大小

        

        静态成员变量,可以像正常变量一样在成员函数中被访问

        

        而且,静态成员变量是属于整个类的,在没有任何对象的情况下,也存在,那么如何使用呢?

                a. 通过类名访问  ----->  成员变量必须是公用的,一般不这么设计

                        cout << Student::count << endl;

                

                b. 静态成员函数

(2) 静态成员函数

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

        

        特点:

                静态成员函数可以直接通过类名调用,不需要通过特定的对象访问

        

        // 静态成员函数不需要通过对象名调用(不依赖对象,静态成员函数中没有this指针)

        cout << Student::GetCount() << endl;

        

        普通成员函数为什么需要依赖对象?

                因为普通的成员函数默认有一个参数,需要一个this指针

                t1.show(); ---> show(&t1);
 

        静态成员函数的调用:

                1. 可以不通过对象,直接通过类名调用

                        类名::静态成员函数();

                        如:

                        cout << Student::GetCount() << endl;

                

                2. 静态成员函数也可以像普通成员函数一样,使用对象调用(静态成员函数依然是成员函数,只不过没有this指针)

                        对象名.静态成员函数名();

                        or

                        对象指针->静态成员函数名();

                        如:

                        count << s1.GetCount() << endl;

注意:

        1. 静态成员函数中没有 this 指针(非静态成员函数中才有 this 指针)

                this指针表示调用者对象的地址,静态成员函数可以直接通过类名调用

                有可能在调用前,类都没有实例化对象

                

        2. 静态成员函数中不能访问非静态成员(静态成员函数没有 this 指针)

                a. 当对象不存在时,静态成员函数可以直接通过类名调用,但是非静态成员是属于某一个对象的

                b. 在成员函数中,能够对非静态成员的访问,其实都是this的隐式使用,既然在静态成员函数中没有this指针,那么就不可以访问非静态成员变量
                

        3. 静态成员函数不能是const函数

                const修饰成员函数其实修饰的是成员函数的this指针,静态函数都没有this指针!!!

                const修饰函数的作用是避免在函数内部修改当前对象的状态,静态成员函数都不能访问对象的属性(非静态成员变量),肯定是不能修改对象的状态的

                

        4. 静态成员不属于任何对象,而是与类同时存在,属于该类型

                即静态成员不依赖于某一个对象

                很多情况下,静态成员函数都是配合静态成员变量使用的

                

        5. 构造函数和析构函数可以是static吗?

                不能!!!

                        构造函数是对对象进行初始化的,析构函数是释放对象占用的资源,肯定需要可以访问对象的普通成员属性

        

        6. 声明和定义分开时,定义不能加static修饰

#include <iostream>
#include <string.h>

using namespace std;

class Test {
    private:
        int m_a;
    public:
        Test(int a) {
            // this是一个隐藏的参数,表示调用者对象的地址
            // 在此处,表示正在初始化的对象的地址
            this->m_a = a;
            cout << "构造函数:this" << this << endl;
            // show(); ===> this->show(); ===> show(this)
        }
        ~Test() {
            cout << "析构函数:" << this <<endl;
        }
        void show() { // void show(Test* const this)
            // 在成员函数中,对类成员的访问,其实都是this指针的隐式使用
            cout << "show:this:" << this << endl;
            cout << "m_a:" << this->m_a << endl;
            // this = nullptr;  this不允许改变指向,但是允许改变this指向的地址中的内容
            // (*this)  表示调用者对象本身
            (*this).m_a = 100;
        }
};

class Student {
    private:
        // 普通成员变量,每一个对象都有单独的一份拷贝
        int m_age;
        char *m_name;
        // static Test t; // 静态成员对象,在使用前,也需要在类外初始化
        // 使用static修饰的成员就叫做静态成员,静态成员属于整个类,而不是属于某一个对象
        static int count; // 用来统计学生类的所有对象个数

    public:
        // 构造函数 
        Student(const char *name = "zhangsan", int age = 30) : m_age{age} {
            cout << "构造函数" << endl;
            m_name = new char[strlen(name) + 1]; // 开辟空间存储名字
            strcpy(m_name, name);
            count++;
        }

        // 拷贝构造函数
        Student(const Student &oth) : m_age{oth.m_age} {
            cout << "const-拷贝-构造函数" << endl;
            // m_age = oth.m_age;
            // m_name = oth.m_name; // 有问题!!!!
            // a.为新对象开辟空间
            m_name = new char[strlen(oth.m_name) + 1];
            // b.把原有对象的数据赋值给新对象
            strcpy(m_name, oth.m_name);
            count++;
        }

        // 析构函数
        ~Student() {
            cout << "析构函数" << endl;
            delete [] m_name;
            count--;
        }

        // 展示函数
        void show() const {
            cout << "name:" << m_name << endl;
            cout << "age:" << m_age << endl;
            cout << "count" << m_count << endl;
        }

        // 静态成员函数,不需要通过对象调用
        static int GetCount(); // const 静态成员函数不能有const修饰
};

// 声明和定义分开时,定义不能加static修饰
int Student::GetCount() {
    cout << "静态成员函数" << endl;
    // cout << m_age << endl; // 静态成员函数中,不能访问非静态成员
    return count;
}

// 静态成员变量必须在类外初始化
int Student::count = 0;

// Test Student::t{1024}; // 静态成员对象在类外初始化

Student s2; // 全局对象 ---> 静态成员变量在程序运行时,就已经初始化了

int main() {
    cout << "sizeof(Student):" << sizeof(Student) << endl; // 16 不影响 类类型 和 对象 的大小(sizeof) 
    Student s{"ikun", 20};
    Student s1(s); // 拷贝构造函数
    cout << "sizeof(s):" << sizeof(s) << endl; // 16 不影响 类类型 和 对象 的大小(sizeof)

    cout << "count:" << Student::GetCount() << endl; // 静态成员函数,通过类名调用
    // cout << "count:" << s.GetCount() << endl; // 静态成员函数,通过对象调用

   return 0;
}

(3) 一个关于函数指针(保存函数地址的指针变量)的问题

        函数指针:

                返回值  (*指针变量名)(参数列表);

        

        函数:

                void fun(int a, double b);

                定义一个指针p,保存fun的地址

                        void (*p)(int , double); // p就是一个指针变量,可以保存一个void(int,double)函数的地址

                赋值:

                        p = fun;        p = &fun;

                调用:

                        p(1, 1.2);        (*p)(1, 1.2);

        1. 能不能定义一个函数指针,指向类的非静态成员函数

                定义方式:

                        返回值  (类名::*指针变量名)(参数列表);

                        // 返回值  (类名::*指针变量名)(参数列表) const;

                        如:

                        void (Student::*p)();

                        // void (Student::*p)() const;

                

                赋值方式:

                        p = &类名::函数名

                        如:

                        p = &Student::show;

        

                调用:

                        调用必须通过类的对象进行调用,因为有一个this指针的隐藏参数

                        (s1.*p)();

                        // s1是一个指针:(s1->*q)();

        

        2. 能不能定义一个函数指针,指向类的静态成员函数

                定义和使用方式类似于普通的全局变量

                定义方式:

                        返回值  (*指针变量名)(参数列表);  // 返回值  (*指针变量名)(参数列表);

                        如:

                        int (*p)();

                

                赋值方式:

                        p = 类名::函数名;

                        如:

                        p = Student::GetCount;
        

                调用:

                        p();

#include <iostream>
#include <string.h>

using namespace std;

class Student {
    private:
        // 普通成员变量,每一个对象都有单独的一份拷贝
        int m_age;
        char *m_name;
        // 使用static修饰的成员就叫做静态成员,静态成员属于整个类,而不是属于某一个对象
        static int count; // 用来统计学生类的所有对象个数

    public:
        // 构造函数
        Student(const char *name = "zhangsan", int age = 30):m_age{age} {
            cout << "构造函数" << endl;
            m_name = new char[strlen(name) + 1]; // 开辟空间存储名字
            strcpy(m_name, name);
            count++;
        }

        // 拷贝构造函数
        Student(const Student &oth):m_age{oth.m_age} {
            cout << "const-拷贝-构造函数" << endl;
            // m_age = oth.m_age;
            // m_name = oth.m_name; //有问题!!!!
            // a.为新对象开辟空间
            m_name = new char[strlen(oth.m_name) + 1];
            // b.把原有对象的数据赋值给新对象
            strcpy(m_name, oth.m_name);
            count++;
        }

        // 析构函数
        ~Student() {
            cout << "析构函数" <<endl;
            delete [] m_name;
            count--;
        }

        // 展示函数
        void show()  const {
            cout << "name:" << m_name << endl;
            cout << "age:" << m_age << endl;
            cout << "count:" << count << endl;
        }

        // 静态成员函数,不需要通过对象调用
        static int getCount() { // const   静态成员函数不能有const修饰
            cout << "静态成员函数" << endl;
            // cout << m_age << endl; // 静态成员函数中,不能访问非静态成员
            return count;
        }
};

//静态成员变量必须在类外初始化
int Student::count=0;  

// 普通的函数
void fun(int a, double b) {
    cout << "function" << endl;
    cout << "a:" << a << endl;
    cout << "b:" << b << endl;
}

int main() {

    // 1.函数指针指向普通函数
    // 定义
    void (*p)(int, double);
    // 赋值
    p = fun; // p = &fun;
    // 调用
    p(1, 1.2); // (*p)(1, 1.2);

    cout << "=======================" << endl;

    // 2.函数指针指向类的非静态成员函数
    // 定义方式: 
        // 返回值 (类名::*指针变量名)(参数列表); 
        // 返回值 (类名::*指针变量名)(参数列表) const; 
    // 需要说明指向哪一个类的函数
    void (Student::*q)() const;  
    // 赋值方式:
    q = &Student::show;
    // 调用:调用必须通过类的对象进行调用,因为有一个this指针的隐藏参数
    Student s1{"ikun",30};
    // 如果s1是一个指针: (s1->*q)();
    (s1.*q)();

    cout << "=======================" << endl;

    // 3.函数指针指向类的静态成员函数,定义和使用方式类似于普通的全局函数
    // 定义方式: 返回值 (*指针变量名)(参数列表);
    int (*pf)();
    // 赋值方式:p = 类名::函数名;
    pf = Student::getCount;
    // 调用:
    cout << pf() << endl;

    return 0;
}

(4) 练习

设计一个日期类,实现获取"当天"的日期,使用静态成员函数

#include <iostream>
#include <time.h>

using namespace std;

class Date {
    private:
        int m_year; // 年
        int m_mon; // 月
        int m_day; // 日
        int m_hour; // 时
        int m_min; // 分
        int m_sec; // 秒
    public:
       Date(int year = 2024, int mon = 1, int day = 1, int hour = 1, int min = 1, int sec = 1);
       Date(const Date &d);
       ~Date();
       void show();
       void setDate(int year = 2024, int mon = 1, int day = 1, int hour = 1, int min = 1, int sec = 1);
       // 每次调用函数可以获取当天日期
       static Date getToday();
};

Date::Date(int year, int mon, int day, int hour, int min, int sec) : m_year{year}, m_mon{mon}, m_day{day}, m_hour{hour}, m_min{min}, m_sec{sec} {
    cout << "构造函数" << endl;
}

Date::Date(const Date &d) : m_year{d.m_year}, m_mon{d.m_mon}, m_day{d.m_day}, m_hour{d.m_hour}, m_min{d.m_min}, m_sec{d.m_sec} {
    cout << "拷贝构造函数" << endl;
}

Date::~Date() {
    cout << "~析构函数" << endl;
}

void Date::show() {
    // cout << "Date(" << m_year << "-" << m_mon << "-" << m_day << " " << m_hour << "-" << m_min << "-" << m_sec << ")" << endl;
    cout << "Date(" << m_year << "-" << m_mon << "-" << m_day << " " << m_hour << "-" << m_min << "-" << m_sec << ")" << endl;
}

void Date::setDate(int year, int mon, int day, int hour, int min, int sec) {
    m_year = year;
    m_mon = mon;
    m_day = day;
    m_hour = hour;
    m_min = min;
    m_sec = sec;
}

// 每次调用函数可以获取当天日期
Date Date::getToday() {
    // 获取系统当前时间
    time_t tm; // 保存当前的时间(秒数)
    /*
        time_t time(time_t *tloc);
            time函数接受一个指向time_t类型的指针t作为参数,返回自1970年1月1日以来的秒数,
            并将结果存储在t指向的内存位置中。如果t为NULL,则函数只返回秒数而不存储结果
    */
    time(&tm);
    /*
        struct tm *localtime(const time_t *timep);
            struct tm {
                int tm_sec;    // 秒,范围从 0 到 59     
                int tm_min;    // 分,范围从 0 到 59
                int tm_hour;   // 小时,范围从 0 到 23
                int tm_mday;   // 一月中的第几天,范围从 1 到 31
                int tm_mon;    // 月份,范围从 0 到 11
                int tm_year;   // 自 1900 起的年数
                int tm_wday;   // 一周中的第几天,范围从 0 到 6
                int tm_yday;   // 一年中的第几天,范围从 0 到 365
                int tm_isdst;  // 夏令时 
            };
    */
    // 将秒数转换为日期,时间,返回一个结构体指针
    struct tm *pt = localtime(&tm);
    return Date{pt->tm_year + 1900, pt->tm_mon + 1, pt->tm_mday, pt->tm_hour, pt->tm_min, pt->tm_sec};
}

int main() {

    // Date d;
    // d.show();

    // 通过类名调用静态函数,获取当前的日期!!!
    Date d = Date::getToday();
    d.show();

    return 0;
}

/*
构造函数
Date(2024-11-11 16-54-21)
~析构函数
*/

03 关键字 delete 和 default

delete 关键字:

1. 用于释放new出来的动态内存

2. 用于删除编译器自动生成的某些函数(如:拷贝构造函数) -----> C++11

class Demo {
    private:
        Demo(const Demo&) = delete; // 写了这个,就不会生成默认构造函数了
};

delete 关键字:

1. 用于 switch...case...中,表示默认情况

2. 用于 要求编译器生成某些 本该生成的函数(如:默认构造函数) ----->C++11

class Demo {
    private:
        Demo(const Demo&) = delete;
    public:
        Demo() = default;
}

04 单例模式

单例模式是经典设计模式中的一种


程序在运行的时候,通常每一个类都会实例化很多个对象,如:string类的实例,当有100个字符串时,string就会实例化100个string类型的对象

但是,当我们想在程序中表示某一个对象的时候,并且这个对象永远只会存在一个,无论在哪里创建/访问都只会用到哪个唯一的实例,就会有"类只能实例化一个对象"的需求

        如:回收站、任务管理器、数据库连接对象、LCD屏幕......

像这种确保一个类只生成一个实例化的模式,称为单例模式(SingleTon)


如何实现:

        1. 确保用户无法自己创建对象(只需要把构造函数设置为私有的,删除拷贝构造函数)

        2. 让类自己负责管理这唯一的一个对象(使用静态成员对象)

        3. 提供一个安全的全局访问点,即提供一个公共的接口,让用户可以使用(获取)这唯一的一个实例

实现方式:

        不同的语言,不同的程序员,可能有很多种实现方式,总体可以分为以下两种

                饿汉式(预先创建)、懒汉式(延时创建)

        

饿汉式(预先创建):

        唯一的实例在类加载的时候就创建,预先初始化(不管有没有用到都创建这个实例)

        线程安全的,可以避免多任务的时候出现多次创建的情况

        在类加载的时候创建,调用的时候反应速度快

        在类加载的时候创建,有可能永远也用不到这个实例(资源浪费)

#include <iostream>

using namespace std;

// 单例类,这个类只允许有一个实例

class SingleTon {
    private:
        int _value;
        // 构造函数私有化(防止用户实例化对象)
        SingleTon(int val = 1024) : _value{val} {
            cout << "构造函数" << endl;
        }
        // 不让编译器默认生成拷贝构造函数
        // =delete 的意思是不需要编译器生成默认的函数
        SingleTon(const SingleTon &) = delete;

        // 使用静态成员对象,作为这个类唯一的一个实例,只要包含了这个类,这个实例就会被创建
        // 静态成员,在程序运行前会被构造,在程序结束后被析构
        static SingleTon s; // 类唯一的一个实例!!!

    public:
        ~SingleTon() {
            cout << "析构函数" << endl;
        }
        void show() {
            cout << "value:" << _value << endl;
            cout << "this:" << this << endl;
        }
        void set(int val) {
            this->_value = val;
        }

        // 提供一个静态函数,这个静态函数可以获取这唯一的一个实例对象!!!
        static SingleTon & getInstance() { // 此次必须返回引用,因为拷贝构造函数被删除了
            return s; // 返回静态对象本身!
        }
};

// 静态成员对象必须在类外初始化
SingleTon SingleTon::s{100};

void fun() {
    SingleTon &s = SingleTon::getInstance();
    s.show();
    s.set(1234);
}

int main() {
    cout << "======================" << endl;
    // SingleTon s{100}; 无法自己创建实例

    // SingleTon s1 = SingleTon::getInstance(); // 拷贝构造函数被删除了

    // s1成为了唯一的那一个实例的别名
    SingleTon &s1 = SingleTon::getInstance();
    s1.show();

    fun();

    SingleTon &s2 = SingleTon::getInstance();
    s2.show();

    cout << "======================" << endl;
    return 0;
}

构造函数
======================
value:100
this:0x55b9c6357134
value:100
this:0x55b9c6357134
value:1234
this:0x55b9c6357134
======================
析构函数

懒汉式(延时创建):

        唯一的实例在第一次调用获取实例的时候才会被创建,延时初始化(不用到就可能永远不会创建)
        可能是非线程安全的(C++11后,规定静态对象是线程安全的)
        避免了饿汉式那种在没有用到的情况下也会创建实例的问题,资源利用率高
        在使用的时候才会创建,调用的时候反应速度没有饿汉式快

#include <iostream>

using namespace std;

// 单例类,这个类只允许有一个实例

class SingleTon {
    private:
        int _value;
        // 构造函数私有化(防止用户实例化对象)
        SingleTon(int val = 1024) : _value{val} {
            cout << "构造函数" << endl;
        }
        // 不让编译器默认生成拷贝构造函数
        // =delete 的意思是不需要编译器生成默认的函数
        SingleTon(const SingleTon &) = delete;
    public:
        ~SingleTon() {
            cout << "析构函数" << endl;
        }
        void show() {
            cout << "value:" << _value << endl;
            cout << "this:" << this << endl;
        }
        void set(int val) {
            this->_value = val;
        }
        // 提供一个静态函数,这个静态函数可以获取这唯一的一个实例对象!!!
        static SingleTon & getInstance() { // 此次必须返回引用,因为拷贝构造函数被删除了
            // 局部静态对象,这个函数没有被访问,就不会被创建
            static SingleTon s{100}; // 只会被初始化一次,生存期是随进程的持续性
            return s;
        }
};

void fun() {
    SingleTon &s = SingleTon::getInstance();
    s.show();
    s.set(1234);
}

int main() {
    cout << "======================" << endl;
    // SingleTon s{100}; // 无法自己创建实例

    // SingleTon s1 = SingleTon::getInstance(); // 拷贝构造函数被删除了

    // s1成为了唯一的那一个实例的别名
    SingleTon &s1 = SingleTon::getInstance();
    s1.show();

    fun();

    SingleTon &s2 = SingleTon::getInstance();
    s2.show();

    cout << "======================" << endl;
    return 0;
}

======================
构造函数
value:100
this:0x55b7143c3134
value:100
this:0x55b7143c3134
value:1234
this:0x55b7143c3134
======================
析构函数

将屏幕类设计为单例模式:

饿汉式

懒汉式

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值