文章目录
- 构造函数、析构函数和封装案例
- 1. 构造函数和析构函数
- 1.1 概述
- 1.2 案例
- 1.3 编译器自行提供构造函数
- 1.4 拷贝构造函数和特殊用法
- 1.5 构造函数总结和要求
- 2. 封装案例
- 2.1 封装的终极奥义
- 2.2 封装一个 Cube 立方体
构造函数、析构函数和封装案例
1. 构造函数和析构函数
1.1 概述
构造函数用途
- 首先配合 new 关键字使用
- new 关键字根据构造函数名称对应的数据类型,在内存【堆区】申请必要的内存空间
- 构造函数将对应的内存空间进行初始化赋值操作
格式和要求
- 构造函数名称必须是【类名】
- 构造函数没有返回值类型,也不需要使用 void 或者 void * 占位
- 初始化操作列表根据当前实际所需完成
类名(必要的初始化参数列表)
{初始化语句;
}
1.2 案例
#include <iostream>#include <cstdio>
#include <cstdlib>
#include <cstring>using namespace std;class Person
{
public:/*当前函数就是一个构造函数,函数名对应当前的类名,函数的形式参数列表为空【无参数的构造函数】*/Person(){// id 和 age 初始化id = 0;age = 0;// 构造函数,对 name 成员变量使用操作所需的内存空间进行申请和擦除name = (char *)malloc(32);memset(name, 0, 32);// name = "James";}// 有参数构造函数给予变量进行赋值操作Person(int id, char *name, int age){this->id = id;this->age = age;this->name = (char *)malloc(32);memset(this->name, 0, 32);strcpy(this->name, name);}// 【拷贝构造函数】将参数 Person 对象数据内容,完整的拷贝一份给予当前实例化// Person 对象。当前参数是一个 Person & ,可以认为是用于初始化当前对象的数据载体// 将参数 Person 中的成员变量数据,赋值给新实例化对象Person(const Person & person){// 将参数 person 中的数据内容,赋值给当前的新对象中id = person.id;age = person.age;name = (char *)calloc(1, 32);strcpy(name, person.name);}~Person(){// delete 关键字销毁当前 new 创建的对象,会自动调用析构函数// 可以在析构函数中,释放成员变量或者其他操作申请的空间或资源// name 成员变量的数据内容时通过 malloc 申请的,需要通过 free 释放// 避免内存泄漏free(name);}void setId(int id) { this->id = id; }int getId() { return id; }void setName(char *name) { strcpy(this->name, name);}char * getName() { return name; }void setAge(int age) { this->age = age; }int getAge() { return age; }private:int id;char *name;int age;
};int main(int argc, char const *argv[])
{/*new Person; 没有明确任何参数,对应无参数构造参数new Person; // <==> new Person();*/Person *p = new Person;cout << "ID : " << p->getId() << endl;cout << "Name : " << p->getName() << endl;cout << "Age : " << p->getAge() << endl;cout << "----------------------------------" << endl;/*利用实际参数,告知编译器,当前选择的构造函数时有参构造函数这里利用得时函数的【重载】*/Person *p1 = new Person(3, "Wade", 32);cout << "ID : " << p1->getId() << endl;cout << "Name : " << p1->getName() << endl;cout << "Age : " << p1->getAge() << endl;cout << "---------------------------------" << endl;Person *p2 = new Person(*p1);cout << "p1 : " << p1 << endl;cout << "p2 : " << p2 << endl;cout << "ID : " << p2->getId() << endl;cout << "Name : " << p2->getName() << endl;cout << "Age : " << p2->getAge() << endl;/*class 类型,通过 delete 释放 new 申请的空间,会自动调用当前类中的析构函数 ~Person()delete 本是就是用于释放通过 new 申请的内存空间同时可以在析构函数中,释放/关闭其他必要的资源*/delete p;delete p1;delete p2;return 0;
}
1.3 编译器自行提供构造函数
#include <iostream>using namespace std;/*
一个类没有【显式】定义构造函数,系统会自动给提供两个构造函数和默认析构函数1. 无参数构造函数【注意】如果代码中存在任何一个【显式】定义的构造函数,编译器不再提供默认无参数构造函数2. 拷贝构造函数:根据当前类中的成员变量数据情况,进行成员变量逐一拷贝赋值3. 默认析构函数*/
class Person
{
public:int id;string name;int age;// Person(int id) { this->id = id; }
};int main(int argc, char const *argv[])
{// 调用系统的无参数构造函数Person *p = new Person();p->id = 10;p->name = "Mary";p->age = 13;// 调用系统提供的默认拷贝构造函数Person *p1 = new Person(*p);cout << "ID : " << p1->id << endl;cout << "Name : " << p1->name << endl;cout << "Age : " << p1->age << endl;delete p;delete p1;return 0;
}
1.4 拷贝构造函数和特殊用法
同类型变量赋值操作,会调用拷贝函数完成对应代码
#include <iostream>using namespace std;class Person
{
public:int id;string name;int age;Person() {}Person(int id, string name, int age){this->id = id;this->name = name;this->age = age;}// Person(int id) { this->id = id; }Person(const Person &person){id = person.id;name = person.name;age = person.age;cout << "拷贝构造函数执行" << endl;}
};int main(int argc, char const *argv[])
{Person p;p.id = 1;p.name = "张三";p.age = 17;/*发现代码中调用拷贝构造函数执行这里存在类重载 = 赋值号运算符的效果,将 p 数据赋值给 p1c++ 会自动调用拷贝构造函数,将 p 中的数据通过拷贝构造赋值给 p1 中的数据内容*/Person p1 = p;cout << "ID : " << p1.id << endl;cout << "Name : " << p1.name << endl;cout << "Age : " << p1.age << endl;// 不同的地址cout << "p1 : " << &p1 << endl;cout << "p : " << &p << endl;return 0;
}
1.5 构造函数总结和要求
- 任何一个定义类,必须提供无参数构造函数
- 利用析构函数逻辑,一定要对当前对象使用的其他内存空间,或者必要的资源进行释放操作。
- 拷贝构造函数是将参数对象的数据内容,赋值给当前对象,如果是在使用 = 赋值运算符,也会调用拷贝构造函数
2. 封装案例
2.1 封装的终极奥义
- 一个代码如果使用三次以上,封装一个函数
- 一组函数使用三次以上,封装一个工具
- 一个工具开发中使用了三次以上,完成对应的完备的文档
2.2 封装一个 Cube 立方体
#include <iostream>using namespace std;class Cube
{
public:// 构造函数Cube() {}Cube(int length, int width, int height){this->length = length;this->width = width;this->height = height;}Cube(const Cube & cube): length(cube.length), width(cube.width), height(cube.height) {}~Cube() {}// 设置成员变量和成员变量数据相关函数void setLength(int length) { this->length = length; }int getLength() { return length; }void setWidth(int width) { this->width = width; }int getWidth() { return width; }void setHeight(int height) { this->height = height; }int getHeight() { return height; }// 体积获取int getVolume(){return length * width * height;}// 面积获取int getArea(){return 2 * (length * width + length * height + width * height);}private:// 成员变量全部私有化,需要提供对应的 set 和 get 函数完成成员变量赋值和取值操作int length;int width;int height;
};int main(int argc, char const *argv[])
{Cube * c1 = new Cube(10, 10, 10);cout << "Volume : " << c1->getVolume() << endl; // 1000cout << "Area : " << c1->getArea() << endl; // 600return 0;
}