塑胶材料东莞网站建设,下面什么不属于网络推广方法,厦门有没网站建设的公司,wordpress导航栏添加按钮目录
类的6个默认成员函数
构造函数
语法
特性
析构函数
特性
对象的销毁顺序 类的6个默认成员函数
问题#xff1a;一个什么成员都没的类叫做空类#xff0c;空类中真的什么都没有吗#xff1f;
基本概念#xff1a;任何类在什么都不…目录
类的6个默认成员函数
构造函数
语法
特性
析构函数
特性
对象的销毁顺序 类的6个默认成员函数
问题一个什么成员都没的类叫做空类空类中真的什么都没有吗
基本概念任何类在什么都不写时编译器会自动生成以下六个默认成员函数无参的
定义用户没有显式实现编译器会生成的成员函数称为默认成员函数 注意事项如果我们自己实现了这些函数那么编译器就不会生成默认的成员函数
构造函数
产生原因初始化容易被遗忘且有时候会太麻烦
作用完成初始化工作Init
class Date
{
public:void Init(int year, int month, int day){_year year;_month month;_day day;}void Print(){cout _year - _month - _day endl;}private:int _year;int _month;int _day;
};int main()
{Date d1;d1.Init(2022, 7, 5);d1.Print();Date d2;d2.Init(2022, 7, 6);d2.Print();return 0;
} 对于Data类之前我们会通过Init公有方法给对象设置日期但每次创建对象时都需要调用该方法设置信息就显得有点麻烦C的构造函数就可以做到在对象创建时就将信息设置进去
语法
1、构造函数是特殊的成员函数
2、构造函数的主要任务是在类实例化对象时初始化对象而不是去开空间创建对象
3、构造函数的函数名与所在类的类名相同类名是A构造函数的名字就叫A客随主便
4、构造函数无返回值不是void而是连void都没
5、对象实例化时编译器会自动调用合适的构造函数对象后没括号就调无参构造函数有实参就调用带参构造函数
#include iostream
using namespace std;class Date{public:// 1.无参构造函数Date(){_year 1;_month 1;_day 1;}void Print(){cout _year - _month - _day endl;}private:int _year;int _month;int _day;};int main()
{Date d1; // 调用无参构造函数d1.Print();return 0;
} 6、构造函数可以重载
#include iostream
using namespace std;class Date
{
public:// 1.无参构造函数Date(){_year 1;_month 1;_day 1;}void Print(){cout _year - _month - _day endl;}// 2.带参构造函数Date(int year, int month, int day){_year year;_month month;_day day;}
private:int _year;int _month;int _day;
};int main()
{Date d1; // 调用无参构造函数d1.Print();Date d2(2015, 1, 1); // 调用带参的构造函数d2.Print();return 0;
} 7、构造参数没有形参时对象实例化时不能在对象后加括号 8、 对象实例化时必须调用构造函数没有或者没有合适的构造函数就会报错d1原本想要调用无参的构造函数但是只有带参的构造函数有了带参的构造参数编译器就算像提供不带参的默认构造参数也没办法了
#include iostream
using namespace std;class Date
{
public:void Print(){cout _year - _month - _day endl;}//带参构造函数Date(int year, int month, int day){_year year;_month month;_day day;}private:int _year;int _month;int _day;
};int main()
{Date d1;d1.Print();return 0;
} 9、无参的构造函数和全缺省的构造函数在语法上因为函数重载可以同时存在但是在实践中不可以会造成调用歧义
#include iostream
using namespace std;class Date
{
public:Date(){_year 1;_month 1;_day 1;}void Print(){cout _year - _month - _day endl;}Date(int year 1, int month 1, int day 1){_year year;_month month;_day day;}
private:int _year;int _month;int _day;
};int main()
{Date d1;d1.Print();return 0;
} 特性
1重点、实例化对象时我们不写构造函数包括默认构造函数和普通的构造函数编译器就会生成默认构造函数从而初始化对象我们写了构造参数编译器就不会生成默认构造参数普通的构造参数是指带参的构造参数
2、编译器生成的默认构造参数什么也不干为什么我们程序员没有定义一个构造参数是我们的问题但是你编译器既然为我们自动生成了一个默认构造参数你总得让它起点作用吧就是只让成员变量初始化为0也行啊
#include iostream
using namespace std;class Date
{
public:void Print(){cout _year - _month - _day endl;}private:int _year;int _month;int _day;
};int main()
{Date d1;d1.Print();return 0;
} 这是因为C将数据分为了内置基本类型和自定义类型
内置类型语言自身定义的类型int、char、double、任何类型的指针等自定义类型程序员根据自己需求定义的类型struct、class等
3、C98规定编译器生成的默认构造函数程序员没提过时对内置类型不做处理对自定义类型会去调用它的默认构造函数一定是默认构造函数而不是普通的构造函数
#include iostream
using namespace std;//编译器对自定义类型会调用它的默认构造
class A
{
public:A(){cout A() endl;_a 0;}
private:int _a;};//编译器对内置类型不做处理
class Date
{
public://这里没有自定义构造函数编译器默认生成构成函数void Print(){cout _year - _month - _day endl;}private:int _year;int _month;int _day;A _aa;
};int main()
{Date d1;d1.Print();return 0;
} 大致步骤如下①Date d1实例化对象d1
②Data{}编译器自动生成默认构造函数并开始对成员变量开始初始化
③__aa_aa的类型是A类属于自定义类型调用A类的提供的默认构造函数
如果A类也没提供默认构造函数那么_aa也是随机值虽然编译器也可以为A提供但是没用
#include iostream
using namespace std;class A
{
public:int getA() // 添加一个公共方法以获取 _a 的值{return _a;}private:int _a;};class Date
{
public:void Print(){cout Year: _year , Month: _month , Day: _day endl;cout Value of _aa member variable in class Date: _aa.getA() endl; // 打印_aa对象内部_a变量的值}private:int _year;int _month;int _day;A _aa;
};int main()
{Date d1;d1.Print();return 0;
}④_year、_month、_day是int类型属于内置类型不做任何操作结果为随机值 为什么在调试时先初始化对象_aa 答C中类的成员变量初始化顺序是由它们在类中声明的顺序决定的而不是由它们在构造函数初始化列表中出现的顺序决定 注意事项有些新的编译器会对内置类型也做处理但是C的标准没有规定 4、C11规定内置类型的成员变量声明时可给默认值为C98打补丁没给的依然是随机值
#include iostream
using namespace std;class A
{
public:A(){cout A() endl;_a 0;}private:int _a;};class Date
{
public:void Print(){cout _year - _month - _day endl;}private://声明时给缺省值int _year 2024;int _month 3 ;int _day;A _aa;
};int main()
{Date d1;d1.Print();return 0;
} 5、 只有无参 / 全缺省构造函数、编译器默认生成的构造函数都叫默认构造函数其余的都是构造函数而不是默认构造函数默认构造函数只能有一个
//默认构造参数只能有一个
#include iostream
using namespace std;
class Date
{
public://无参的构造函数是默认构造函数Date(){_year 1900;_month 1;_day 1;}//全缺省的构造函数是默认构造函数Date(int year 1900, int month 1, int day 1){_year year;_month month;_day day;}
private:int _year;int _month;int _day;
};int main()
{Date d1;return 0;
} //成员变量在声明时未给缺省值
#include iostream
using namespace std;
class Date
{
public:Date(int year 1, int month , int day){_year year;_month month;_day day;}void Print(){cout _year - _month - _day endl;}~Date(){cout this endl;cout ~Date() endl;}private:int _year;int _month;int _day;};int main()
{Date d1;d1.Print();return 0;
}//成员变量在声明时提供缺省值
#include iostream
using namespace std;
class Date
{
public:Date(int year 1, int month , int day){_year year;_month month;_day day;}void Print(){cout _year - _month - _day endl;}~Date(){cout this endl;cout ~Date() endl;}private:int _year 1;int _month 1;int _day 1;
};int main()
{Date d1;d1.Print();return 0;
} 为什么成员变量在声明时已经给了缺省值为什么Data还要再给 答虽然为 Date 类中的私有成员变量 _year, _month, 和 _day 提供了默认值1, 1, 1但这些缺省值仅在默认构造函数未初始化成员变量时才会被用于初始化成员变量。实例化d1时类中定义了一个貌似是全缺省的构造函数因此编译器不会自动生成默认构造函数那个位置上已经有人了只是那个人有点缺陷且因为该貌似的全缺省构造函数缺少两个缺省值所以报错 #include iostream
using namespace std;class Time
{
public://带参构造函数不是默认构造函数Time(int hour){cout Time() endl;_hour 0;_minute 0;_second 0;}
private:int _hour;int _minute;int _second;
};class Date
{
private://声明给缺省值int _year;int _month;int _day;Time _t;
};int main()
{Date d;return 0;
} 为什么会提示_t没有默认构造函数 答实例化对象d时Date类没给构造函数编译器自动生成默认构造函数无参_year、_month、_day是内置类型不做处理_t是自定义类型会调用Time类的默认构造函数但是Time类中已经有了一个带参的构造函数普通构造函数所以Time类中不会有默认构造函数了只要我们写了构造函数即使它是带参的普通构造函数编译器就不会给我们提供默认构造参数了故报错 结论绝大多数场景下都需要自己实现构造函数且更推荐用全缺省构造函数 析构函数 产生原因需要人为销毁的空间容易忘记销毁内存泄漏可能不会报错
#include iostream
using namespace std;
class Date
{
public:void Print(){cout _year - _month - _day endl;}~Date(){cout this endl;cout ~Date() endl;}private://声明给缺省值int _year 1;int _month 1;int _day 1;};void func()
{Date d2;
}class Stack
{
public:Stack(size_t capacity 4){_array (int*)malloc(sizeof(int*) * capacity);if (NULL _array){perror(malloc申请空间失败!!!);return;}_capacity capacity;_size 0;}void Push(int data){// CheckCapacity();_array[_size] data;_size;}//~Stack()//{// cout ~Stack() endl;// if (_array)// {// free(_array);// _array nullptr;// }// _size _capacity 0;//}private:int* _array;int _capacity;int _size;
};int main()
{func();Date d1;Stack st1; //内存泄漏return 0;
} 如果Stack类中没有自定义的析构函数就会出现内存泄漏因为我们即没有定义Destory函数去销毁在堆上开辟的空间析构函数也不起作用 作用完成清理工作Destory
基本概念析构函数不是完成对对象本身的销毁局部对象销毁工作是由编译器完成的而对象在销毁时会自动调用析构函数完成对象中资源的清理工作
特性
1、析构函数名是在类名前加上字符~
2、析构函数无参数无返回值类型
3、一个类只能有一个析构函数若未显示定义编译器会自动生成默认的析构函数
4、析构函数不能重载清理一遍数据就应该被清理完成
5、对象生命周期结束函数结束时程序会自动调用析构函数
#include iostream
using namespace std;
class Date
{
public:~Date(){cout this endl;cout ~Date() endl;}private://声明给缺省值int _year 1;int _month 1;int _day 1;
};void func()
{Date d2;//实例化对象d2
}//函数结束调用析构函数销毁数据int main()
{func(); Date d1;//实例化对象d1return 0;
}//函数结束调用析构函数销毁数据 6、编译器生成的析构函数对内置成员变量不做处理对自定成员变量会调用它的析构函数
#include iostream
using namespace std;class Time
{
public:~Time(){cout ~Time() endl;}
private:int _hour;int _minute;int _second;
};class Date
{
private:// 基本类型(内置类型)int _year 1970;int _month 1;int _day 1;// 自定义类型Time _t;
};
int main()
{Date d;return 0;
}在main函数中没有直接创建Time类的对象为什么最后会调用Time类的析构函数 答main函数中创建了Date类的对象dd中包含了四个成员变量其中_year、_month、_day是内置类型的成员变量销毁时不需要人为清理资源main函数结束后系统直接回收而_t是Time类的对象为了销毁_t就需要Data类的析构函数但是我们并没有给Date类定义析构函数所以编译器就会为Date类提供一个默认析构函数该函数对于自定义类型的成员变量就会调用它_t的析构函数Time提供的析构函数 7、后定义的先析构定义-开辟帧栈-压栈栈后进先出
#include iostream
using namespace std;
class Date
{
public:~Date(){cout this endl;cout ~Date() endl;}private://声明给缺省值int _year 1;int _month 1;int _day 1;};class Stack
{
public:Stack(int capacity 4){_array (int*)malloc(sizeof(int*) * capacity);if (NULL _array){perror(malloc申请空间失败!!!);return;}_capacity capacity;_size 0;}void Push(int data){// CheckCapacity();_array[_size] data;_size;}~Stack(){cout this endl;cout ~Stack() endl;if (_array){free(_array);_array nullptr;}_size _capacity 0;}
private:int* _array;int _capacity;int _size;
};int main()
{Date d1;Stack st1;return 0;
} 8、如果类中没有申请资源时析构函数可以不写直接使用编译器生成的默认析构函数Date类有资源申请时一定要写否则会造成资源泄漏Stack类 9、自定义类型的本质还是内置类型 对象的销毁顺序
从左至右局部变量后定义的先析构——局部的静态——全局后定义的先析构
当成栈来理解先进后出
#include iostream
using namespace std;
class Date
{
public://全缺省构造函数Date(int year 1){_year year;}~Date(){cout ~Date()- _year endl;}private://声明给缺省值int _year;int _month;int _day;};Date d5(5);//全局
Date d6(6);//全局
static Date d7(7);//全局
static Date d8(8);//全局void func()
{Date d3(3);//局部static Date d4(4);//局部的静态
}int main()
{Date d1(1);//局部Date d2(2);//局部func();return 0;
} #include iostream
using namespace std;
class Date
{
public://全缺省构造函数Date(int year 1){_year year;}~Date(){cout ~Date()- _year endl;}private:int _year;int _month;int _day;};int main()
{Date d1(1);//局部Date d2(2);//局部static Date d3(3);//局部的静态return 0;
} ~over~