类的简介

        类是一种将抽象转换为用户定义类型的C++工具,它将数据表示和操纵数据的方法组合成一个整洁的包。一般来说,类规范由两个部分组成:

类声明:以数据成员(成员属性)的方式描述数据部分,以成员函数(被称为方法)的方式描述公有接口。

类方法定义:描述如何实现类成员函数。

访问控制:

  1. private:私有类成员
  2. public:公有类成员
  3. protected:受保护类成员

this指针

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

this指针的格式

类名 *const this;  ----->不能修改指针指向

使用this指针的场合

1)当成员函数的参数和类中成员属性同名时,需要使用this指针指向本类成员属性

#include <iostream>
using namespace std;

class Rec
{
private:
    int length;    //成员属性
public:
    void set_len(int length);
};

void Rec::set_len(int length)    //成员函数的参数
{
    this->length = length;
}

int main()
{
    Rec r1;    //实例化一个Rec类的类对象r1
    r1.set_len(20);
    return 0;
}

2)在拷贝赋值函数中,需要返回自身的引用,此时也需要使用this指针

#include <iostream>
using namespace std;

//封装 学生 类
class Stu
{
private:
    string name;
    int age;
public:
    //无参构造函数
    Stu() {cout << "无参构造函数" << endl;}

    //有参构造函数
    Stu(string name, int age):name(name),age(age)
    {cout << "有参构造函数" << endl;}

    //拷贝赋值函数
    Stu & operator=(const Stu& other)
    {
        if(this != &other)  //避免自己给自己赋值
        {
            this->name = other.name;
            age = other.age;
            cout << "拷贝赋值函数"  << endl;
        }
        return *this;  //返回自己
    }
    void display()
    {
        cout << name << endl;
    }
};

int main()
{
    Stu s1("zhangsan",12);
    s1.display();

    Stu s2;
    s2 = s1;  //s2.operator=(s1)
    s2.display();

    return 0;
}

类中的特殊成员函数 

构造函数

        当类实例化对象时,系统会自动调用构造函数,系统提供无参构造函数,如果手动定义了有参构造函数,那么系统不会再提供一个无参构造函数,若需使用无参构造函数,则需手动定义。

构造函数的功能

        当类实例化对象时,申请空间

有参构造函数的格式

类名(参数)
{
    函数体;
}

        当构造函数的参数列表为空时,为无参构造函数 ,从这里我们可以得出有参构造函数与无参构造函数实际为函数重载。当定义有构造函数时需要初始化列表。

构造函数的初始化列表

        构造函数提供了初始化列表的机制,可以直接在函数体外执行初始化操作,仅有构造函数能够初始化列表。

格式:

类名(参数1,参数2):成员属性1(参数1),成员属性2(参数2)
            //实例:Stu(string name, int age):name(name),age(age)
{
    函数体;
}

使用初始化列表的情况

  1. 形参和成员属性同名
  2. 类中有引用成员时,需要使用初始化列表
  3. 类中有const修饰的成员时
  4. 一个类中有另一个类的子对象时,需要使用初始化列表(如果两个类都有无参构造,不需要写初始化列表)

析构函数

        析构函数,不支持函数重载,并且析构函数不需要传参数

析构函数的功能

        回收类对象的空间

析构函数的格式

~类名()
{
    函数体;
}

        一般程序结束时,系统调用析构函数回收类对象空间。当类的成员属性含有指针时,需要显示定义析构函数,手动释放指针空间。

#include <iostream>
using namespace std;

class Stu
{
    int *p;
public:
    Stu(int a):p(new int(a)) {}
    ~Stu()
    {
        //在析构之前释放堆区的空间
        delete p;
        p = nullptr;
    }
};

int main()
{
    Stu s1(90);
    return 0;
}

拷贝构造函数

        当使用已有类对象给其他类对象初始化时,系统自动调用拷贝构造函数

拷贝构造函数的功能

        初始化类对象

拷贝构造函数格式

类名(类名 &other)
{
    函数体的内容;
}

拷贝构造函数调用时机

  1. 使用已有的类对象给新的类对象初始化
  2. 当函数的形参是一个类对象时,也会调用拷贝构造函数
  3. 当函数的返回值是一个类对象时,也会调用拷贝构造函数

深浅拷贝问题

        系统默认调用的拷贝构造函数为浅拷贝,当类的成员属性中存在指针时,调用拷贝构造函数需要手动定义深拷贝。 若使用浅拷贝,则两个指针成员指向同一片空间会造成两个问题:

1)对同一片空间二次释放

2)两个指针成员指向同一片空间,发生资源抢占问题

拷贝赋值函数

拷贝赋值函数功能

        使用已有的类对象,给已有的类对象赋值的时候,会调用拷贝赋值函数。

拷贝赋值函数格式

类名 &operator=(const 类名 &other)
{
    函数体;
}

总体示例(封装学生的类,写出构造函数,析构函数、拷贝构造函数、拷贝赋值函数)

#include <iostream>
using namespace std;

//封装 学生 类
class Stu
{
private:
    string name;
    int age;
public:
    //无参构造函数
    Stu() {cout << "无参构造函数" << endl;}

    //有参构造函数
    Stu(string name, int age):name(name),age(age)
    {cout << "有参构造函数" << endl;}

    //拷贝构造函数
    Stu(const Stu& other):name(other.name)
    {
        this->age = other.age;
        cout << "拷贝构造函数" << endl;
    }

    //拷贝赋值函数
    Stu & operator=(const Stu& other)
    {
        if(this != &other)  //避免自己给自己赋值
        {
            this->name = other.name;
            age = other.age;
            cout << "拷贝赋值函数"  << endl;
        }
        return *this;  //返回自己
    }
    ~Stu()
    {
        cout << "析构函数" << endl;
    }
    void display()
    {
        cout << name << endl;
    }
};

int main()
{
    Stu s1("zhangsan",12);
    s1.display();

    Stu s2 = s1;  // s2.Stu(s1)
    s2.display();

    Stu s3;
    s3 = s1;  //s3.operator=(s1)
    s3.display();

    return 0;
}
08-25 11:25