本文PDF下载站点: https://github.com/MrWang522/Private-Document.git
定义:与类名相同的特殊成员函数
语法: ClassName();
作用:完成对属性的初始化
特点: ①. 在定义时可以有参数,也可没有参数 ②. 没有任何返回类型的声明
调用方式: 一般情况下C++编译器会自动调用构造函数, 在一些情况下则需要手工调用构造函数
class MyTest{ public: MyTest() {} // 构造函数: 定义对象时,自动调用该函数,完成对属性的初始化 ~MyTest() {} // 析构函数:对象声明周期结束时,自动调用该函数,释放对象占用的空间 };定义:在构造函数名前加 ‘~’ 的特殊成员函数
语法: ~ClassName();
作用:对象销毁时,自动被调用,用来释放对象占用的空间
特点: ①. 声明的析构函数 没有参数 没有任何返回类型 ②. 在对象销毁时自动被调用
调用方式: 被C++编译器自动调用
注意(重点!!! ):先定义的对象 后析构1. 默认构造函数 2. 无参数构造函数 3. 带参数构造函数 4. 拷贝构造函数
class Test{ public: Test(){ // 1. 无参数构造函数 m_a = 0; m_b = 0; m_c = 0; } Test(int a){ // 2. 有参数构造函数 1个参数 m_a = a; } Test(int a, int b, int c){ // 2. 有参数构造函数 3个参数 m_a = a; m_b = b; m_c = c } Test(const Test& obj ){ // 3 . 拷贝构造函数 /* ... ... */ } private: int m_a, m_b, m_c; };注意:对象初始化 和 对象赋值是两个不同的概念 !!!
/* 1. 括号法 自动调用 */ Test t2(1, 2, 3); // 直接调用三个参数的构造函数: --> 属性初始化值为: m_a = 1; m_b = 2; m_c = 3; /* 2. 等号法 自动调用 */ Test t3 = (1, 2); // 直接调用一个参数的构造函数: --> 属性初始化值为: m_a = 2; 注意:C++等号符功能加强!!!直接取最后一个参数 Test t4 = (1, 2, 3); // 直接调用三个参数的构造函数: --> 属性初始化值为: m_a = 1; m_b = 2; m_c = 3; /* 3. 手动调用 初始化操作 */ Test t5 = Test(1, 2, 3); // 产生匿名对象, 赋给t5, 但只调用一次构造函数, 原因是把匿名对象那块地址 直接命名为t5 !!!作用:用一个对象 去 初始化另外一个对象
class Test{ public: Test(int a, int b){ // 1. 有参数构造函数 2个参数 m_a = a; m_b = b; } Test(const Test& obj ){ // 2 . 拷贝构造函数 m_a = obj.m_a; m_b = obj.m_b; } private: int m_a, m_b; }; void MyTest_03(Test mp){ // 第三种调用测试 /* ... ... */ } Test MyTest_04(){ // 第四种调用测试 Test tmp(1, 2); return tmp; // *******重点!!! 返回一个匿名对象 返回时调用 一次拷贝构造函数(构造的是匿名对象) 在进行一次析构函数(析构的是tmp) } void main(){ Test a(1, 2); /* 第一种调用:直接调用 */ Test b = a; // 1. 不会调用普通构造含糊 直接调用拷贝构造函数!!! // t1 = t2; --> 不会调用拷贝构造函数 这种写法是操作符重载 /* 第二种调用:直接调用 */ Test c(a); // 2. 与上边一样 只是写法不同 /* 第三种调用:类的形参初始化 */ MyTest_03(a); // 3. 此时会调用拷贝构造函数 该函数执行完毕后 调用形参参数的析构函数 /* 第四种调用:函数返回类的匿名对象 */ Test d = MyTest_04(); // 4. 该函数返回了一个匿名对象 使用了匿名对象时 直接把d 的名字给匿名对象(地址不会改变) a = MyTest_04(); // 因为 a 已经被定义,此时匿名对象未使用,则直接调用匿名对象的析构函数 }注意(重点!!! ):操作运算符重载 使用 默认的运算符重载 (浅拷贝) 也会段错误
构造函数初始化列表以一个冒号开始, 以逗号分隔的数据成员列表, 每个数据成员后面跟一个放在括号中的初始化式(所赋的参数)
class CExample { public: CExample(): a(0),b(8.8) {} /* 构造函数初始化列表 */ CExample(){ a=0; b=8.8; } /* 构造函数内部赋值 */ private: int a; float b; };说明: 构造函数 中 调用构造函数 是 不可取 ( 危险 ) 的!!!
class Test{ public: Test(int a, int b, int c){ this->a = a; this->b = b; this->c = c; } Test(int a, int b){ this->a = a; this->b = b; Test(a, b, 100); // 产生新的匿名对象, 对原有的 属性并无影响,并且执行完此函数后 匿名对象被析构 } private: int a, b, c; } void MyTest(){ Test x(1, 2); cout << "c的值为?" << endl; // C的值是 随机值!! } 运行结果: C的值是 随机值 (没有赋初值)原因: 构造 调用 构造, 产生了新的匿名对象, 对原有的 属性并无影响