Linux 学习记录42(C++篇)

本文详细介绍了C++中的类,包括this指针的使用,类的构造函数、析构函数、拷贝构造函数和拷贝赋值函数的概念、格式、调用时机以及深浅拷贝的区别。此外,还讨论了匿名对象的定义和使用场景,以及类的大小和内存分配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Linux 学习记录42(C++篇)

在这里插入图片描述

一、class 类

1. 类中的this指针

类内默认提供给非静态成员函数的this指针,指针指向类对象本身,哪个对象调用成员函数,this就指向哪个对象

(1. this指针的格式

格式:类名* const this; //不能改变this的指向

(2. 使用this指针

1. 如果函数的形参和成员属性同名时,需要使用this指针解决
2. 拷贝赋值函数中,需要返回自身的引用,也需要使用this指针解决
class Rectangle
{
private://私有的成员属性/方法
    int a;
public://公有的成员属性/方法
    void set_a(int a)
    {
"在这里函数的参数a和类中的a变量名重复所以无法确定到底是那个变量,所以需要用到this指针"
        a = a;
    }

protected://受保护的成员属性/方法
};
============================修改后如下================================
class Rectangle
{
private://私有的成员属性/方法
    int a;
public://公有的成员属性/方法
    void set_a(int a)
    {
         this->a = a;
    }
protected://受保护的成员属性/方法
};

2. 类中特殊的成员函数

如果程序员不手动定义,系统会默认提供的函数,系统默认提供的是无参构造

1. 构造函数 (常用)
2. 析构函数 (常用)
3. 拷贝构造函数 (常用)
4. 拷贝赋值函数 (常用)
5. 取地址运算符重载函数
6. 常取地址运算符重载函数
7. C++11新增:移动构造函数
8. C++11新增:移动赋值函数

(1. 构造函数

使用情景:
1. 形参和成员属性同名
2. 类内有引用成员,必须使用初始化列表
3. 类内有const修饰的成员时,必须使用初始化列表
4. 类中包含其他类的的子对象时,其他类必须初始化时,需要使用初始化列表
>1 格式/定义

用于实例化类对象时,系统自动调用

功能:实例化类对象时,给类对象开辟空间和初始化
格式:类名(形参列表)
{
	函数体;
}
例:
class test
{
private://私有的成员属性/方法
    int a;
    string b;
    double c;
public://公有的成员属性/方法
    /*有参构造和无参构造构成函数重载*/
    test(int a,string b,double c)
    {   //有参构造
        this->a=a;
        this->b=b;
        this->c=c;
    }
    test()
    {
        //无参构造
    }
protected://受保护的成员属性/方法
};

int main()
{
    test p;
    test p1(1,"abc",1.23);
    return 0;
}
>2 调用构造函数的时机

构造函数一般是public权限的

  1. 在栈区

什么时候实例化对象,什么时候调用构造函数,系统默认调用

  1. 在堆区申请空间

什么时候用new申请空间,什么时候调用构造函数

>3 构造函数的初始化列表

构造函数提供了初始化列表的机制,在函数体外

格式: 类名(形参列表):成员属性1(参数1),成员属性2(参数2),成员属性3(参数3)...
{
	函数体
}
例:
class test
{
private://私有的成员属性/方法
    int a;
    string b;
    double c;
public://公有的成员属性/方法
    /*有参构造和无参构造构成函数重载*/
    test(int a,string b,double c):a(a),b(b),c(c)
    {   //有参构造
        /*函数体内的赋值
        this->a=a;
        this->b=b;
        this->c=c;*/
    }
protected://受保护的成员属性/方法
};

(2. 析构函数

>1 功能/格式

功能:在类对象消亡时回收类对象的空间

格式:
~类名()
{
	函数体
}
>2 析构函数的调用时机

先构造的后析构

  1. 在栈区:

系统在对象消亡时,主动调用

  1. 在堆区:

使用delete关键字,释放空间时,主动调用析构函数

>3 需要显性调用析构函数情况
1. 系统会默认析构函数,在对象消亡时,主动调用,释放对象的空间
2. 析构函数不允许函数重载
3. 当类中有指针成员(指向堆区申请的空间)时,
>4 定义和使用

析构函数不支持重载

class test
{
private://私有的成员属性/方法
    int a;
    int* p;
    string b;
    double c;
public://公有的成员属性/方法
    /*析构函数,会自动调用*/
    ~test()
    {
        /*释放指针指向的堆区空间地址*/
        delete p;
        p = nullptr;
    }
protected://受保护的成员属性/方法
};

int main()
{
    test* p = new test;
    delete p;
    return 0;
}

(3. 拷贝构造函数

使用已有类对象给新的类对象初始化时,会自动调用拷贝构造函数

>1 格式
类名(类名 &other)
{
	函数体;
}
>2 调用时机
1. 使用已有的类对象给新的类对象初始化的时候,主动调用拷贝构造函数
2. 类对象作为函数的形参,主动调用拷贝构造函数
3. 类对象作为函数的返回值,主动调用拷贝构造函数
>3 定义和使用
class test
{
private://私有的成员属性/方法
    int num;
    string str;
public://公有的成员属性/方法
    test()
    {//无参构造函数
    }
    test(test &other)
    {//拷贝构造函数
        num = other.num;
        str = other.str;
    }
protected://受保护的成员属性/方法
};

int main()
{
    test p1;//定义一个p1变量
    test p2 = p1;//将p1拷贝一份给p2
    return 0;
}
>4. 深/浅拷贝

如果类内有指针成员,涉及到深浅拷贝问题

  1. 浅拷贝

两个不同类对象的指针成员指向同一片空间,会造成一个类对象对其修改另一个类对象的值也会修改

  1. 深拷贝

两个不同类对象的指针成员指向不同的空间,一个类对象的修改不会影响另一个类对象的值。

(4. 拷贝赋值函数

使用一个类对象给另一个类对象赋值时使用的,适于运算符重载

>1 格式

运算符重载的函数名:operator=

类名 &(const 类名 &引用)
{
	函数体;
}
拷贝赋值函数会返回自身的引用
>2 定义
class test
{
private://私有的成员属性/方法
    int num;
    string str;
public://公有的成员属性/方法
    test()
    {
    }
    test &operator=(test &other)
    {
        num = other.num;
        str = other.str;
        return *this;//返回自身
    }
protected://受保护的成员属性/方法
};
>3. 深/浅拷贝

拷贝赋值函数依然需要考虑深浅的问题,但是不需要再申请空间
要保证指针成员指向的地址在堆区才能delete释放

using namespace std;

class test
{
private://私有的成员属性/方法
    int num;
    int* p;
    string str;
public://公有的成员属性/方法
    test()
    {
    }
    test(int a,int* b,string c):num(a),p(b),str(c)
    {
    }
    test &operator=(test &other)
    {
        cout << "拷贝赋值" <<endl;
        *p = *(other.p);//深拷贝
//        p = other.p;//浅拷贝
        num = other.num;
        str = other.str;
        return *this;//返回自身
    }
    void show(void)
    {
        cout << "p=" << p <<endl;
        cout << "num=" << *p <<endl;
    }
    ~test()
    {
        cout << "空间已释放" <<endl;
        delete p;
        p = nullptr;
    }
protected://受保护的成员属性/方法
};

int main()
{
    int num1 = 1;
    int num2 = 2;
    test buf1(num1,&num1,"buf1");
    test buf2(num2,&num2,"buf2");

    buf1.show();
    buf2.show();

    buf1 = buf2;
    cout << "--------" <<endl;

    buf1.show();
    buf2.show();

    return 0;
}

3. 匿名对象

匿名对象就是实例化对象时,没有实例名的对象,它的生命周期短,是一个临时值

(1.使用场景

使用场景:
1. 用作全局函数的临时传参
2. 使用临时对象给另一个类对象赋值
3. 临时使用成员方法
4. 类对象数组

(2. 定义

class test
{
private://私有的成员属性/方法
    int num;
    int* p;
    string str;
public://公有的成员属性/方法
    test(int a,int* b,string c):num(a),p(b),str(c)
    {
    }
protected://受保护的成员属性/方法
};

int main()
{
    int num1 = 1;
    test (num1,&num1,"buf1");//这里就实例化了一个匿名对象
    return 0; 
}

4. 类的大小

类的大小和结构体的大小是一致的,类中的函数在声明时也是不占用空间的
string类型 在64位占32个字节,32位占24字节(QT内)

string类型包含以下几个部分(QT中)
1. 指向字符数组的指针
2. 字符串的实际长度 size_t
3. 字符串能存储的最大长度
4. 系统能存储的最大长度

思维导图

在这里插入图片描述

练习

#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdio>

using namespace std;

class Person
{
private:
    int age;
    int *p;
public:
    //无参构造
    Person():p(new int(89))
    {
        age = 18;
    }
    //有参构造
    Person(int age,int num)
    {
        this->age = age;
        this->p=new int(num);
    }
    //拷贝构造函数
    Person(Person &other)
    {
        age = other.age;
        p = new int (*(other.p));//深拷贝
//        p = other.p;//浅拷贝
    }
    //拷贝赋值函数
    Person operator=(Person &other)
    {
        age = other.age;
        *p = *(other.p);//深拷贝
//        p = other.p;//浅拷贝
        return *this;
    }
    //析构函数
    ~Person()
    {
        delete p;
        p = nullptr;
    }
};

int main()
{

    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值