类的简介
类是一种将抽象转换为用户定义类型的C++工具,它将数据表示和操纵数据的方法组合成一个整洁的包。一般来说,类规范由两个部分组成:
类声明:以数据成员(成员属性)的方式描述数据部分,以成员函数(被称为方法)的方式描述公有接口。
类方法定义:描述如何实现类成员函数。
访问控制:
- private:私有类成员
- public:公有类成员
- 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)
{
函数体;
}
使用初始化列表的情况
- 形参和成员属性同名
- 类中有引用成员时,需要使用初始化列表
- 类中有const修饰的成员时
- 一个类中有另一个类的子对象时,需要使用初始化列表(如果两个类都有无参构造,不需要写初始化列表)
析构函数
析构函数,不支持函数重载,并且析构函数不需要传参数
析构函数的功能
回收类对象的空间
析构函数的格式
~类名()
{
函数体;
}
一般程序结束时,系统调用析构函数回收类对象空间。当类的成员属性含有指针时,需要显示定义析构函数,手动释放指针空间。
#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)两个指针成员指向同一片空间,发生资源抢占问题
拷贝赋值函数
拷贝赋值函数功能
使用已有的类对象,给已有的类对象赋值的时候,会调用拷贝赋值函数。
拷贝赋值函数格式
类名 &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;
}