asp.net 网站安装,无货电商怎么入门,嘉兴网站建设制作,wordpress手机版中文版目录
类的6个默认成员函数
构造函数
语法
特性
析构函数
特性 类的6个默认成员函数
问题#xff1a;一个什么成员都没的类叫做空类#xff0c;空类中真的什么都没有吗#xff1f;
基本概念#xff1a;任何类在什么都不写时#xff0c;编译器会自动生成以下六个默认…目录
类的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、 对象实例化时必须调用构造函数没有或者没有合适的构造函数也会报错
#include iostream
using namespace std;class Date
{
public: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这里原本想要调用无参的构造函数但是只有带参的构造函数d1.Print();return 0;
} 9、可以利用缺省参数将无参和有参的构造函数合并减少代码量
#include iostream
using namespace std;class Date
{
public: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;
} 10、无参的构造函数和全缺省的构造函数在理论上因为构成函数重载可以同时存在但是在实践中不可以同时存在因为会造成调用歧义
#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、实例化对象时我们不写构造函数编译器就会自动生成无参的构造函数从而初始化对象但是实际上编译器默认生成的无参的构造参数什么也不干为什么我们程序员没有定义一个构造参数是我们的问题但是你编译器既然为我们自动生成了一个无参的构造参数你总得让它起点作用吧就是只让成员变量初始化为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等
2、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{}Date类没有定义构造函数编译器自动生成构造函数并开始对成员变量开始初始化
③__aa_aa的类型是A类属于自定义类型调用A类的提供的构造函数A打印A()给a赋值
如果A类也没提供构造函数那么_aa也是随机值
#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的标准没有规定 3、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;
} 4、 无参构造函数、全缺省构造函数、编译器生成的构造函数称为默认构造函数有且只有一个
#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 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、编译器生成的析构函数对内置类型成员不做处理对自定义类型会调用它的析构函数
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类
~over~