有趣的设计网站,做个购物商城网站多长时间,图片演示dw做网站,瑞金网站建设上次为类与对象开了一个头#xff1a;C初阶类与对象#xff08;一#xff09;#xff1a;学习类与对象、访问限定符、封装、this指针 今天就来更进一步 文章目录 1.类的6个默认成员函数2.构造函数2.1引入和概念2.2构造函数特性2.2.1特性1~42.2.2注意2.2.3特性5~72.2.4注意 …上次为类与对象开了一个头C初阶类与对象一学习类与对象、访问限定符、封装、this指针 今天就来更进一步 文章目录 1.类的6个默认成员函数2.构造函数2.1引入和概念2.2构造函数特性2.2.1特性1~42.2.2注意2.2.3特性5~72.2.4注意 3.析构函数3.1概念3.2特性 1.类的6个默认成员函数 如果一个类中什么成员都没有简称为空类。 空类中并不是什么都没有任何类在什么都不写时编译器会自动生成上面6个默认成员函数。 默认成员函数用户没有显式实现编译器会生成的成员函数称为默认成员函数 今天就来主要聚焦于构造函数和析构函数 2.构造函数
2.1引入和概念
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(2023, 10, 19);d1.Print(); return 0;
}每次实例化对象后都要自己进行初始化使用成员函数Init但如果每次创建对象时都调用该方法设置信息未免有点麻烦时不时还会忘记初始化。所以构造函数来了 构造函数是一个特殊的成员函数名字与类名相同,创建类类型对象时由编译器自动调用以保证每个数据成员都有 一个合适的初始值并且在对象整个生命周期内只调用一次 2.2构造函数特性
2.2.1特性1~4 构造函数是特殊的成员函数需要注意的是构造函数虽然名称叫构造但是构造函数的主要任务并不是开空间创建对象而是初始化对象 其特征如下 函数名与类名相同。无返回值(不是写void就是真真正正的没有)。对象实例化时编译器自动调用对应的构造函数。构造函数可以重载 class Date
{
public:Date() //无参构造函数{ _year 1;_month 1;_day 1;}Date(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(); 这样不能调用无参初始化Date d1;//调用无参构造函数d1.Print(); Date d2(2024, 1, 3);//调用带参构造函数d2.Print();return 0;
}2.2.2注意 调用无参初始化时不能加上括号加上后与函数声明无法区分开对有参构造函数使用全缺省可以代替无参构造函数此时虽然二者依然构成重载但是初始化对象不知道调用哪一个。此时只需要一个全缺省构造函数就可以 class Date
{
public:Date(int year1, int month1, int day1)//有参构造函数 二者构成重载{_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.Print();Date d2(2024, 1, 3);//调用带参构造函数d2.Print();Date d3(2024);//传部分也行d3.Print();return 0;
}2.2.3特性5~7 如果类中没有显式定义构造函数则C编译器会自动生成一个无参的默认构造函数一旦用户显式定义编译器将不再生成 如果Date类有自己定义的构造函数代码编译失败因为一旦显式定义任何构造函数编译器将不再生成默认构造函数 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;
}为什么是随机值呢这就牵扯到了特性6了 关于编译器生成的默认成员函数大家会有疑惑不实现构造函数的情况下编译器会生成默认的构造函数。但是看起来默认构造函数又没什么用上面那个例子都是随机值d1对象调用了编译器生成的默认构造函数但是d1对象_year/_month/_day依旧是随机值。也就说在这里编译器生成的默认构造函数并没有什么用 解答C把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型如int/char…自定义类型就是我们使用class/struct/union等自己定义的类型看看下面的程序就会发现编译器生成默认的构造函数会对自定类型成员_t调用的它的默认构造函数,对于内置类型如int、float、指针等默认构造函数不会对其进行任何初始化操作这意味着它们的值将是未定义的可能是随机的 class Stack
{
public:Stack(int capacity 3){_a (int*)malloc(sizeof(int) * capacity);assert(_a);_capacity capacity;_top -1;}private:int* _a;int _top;int _capacity;//这三个是内置类型
};class Queue
{private:Stack _push;//这两个栈都是自定义类型Stack _pop;
};int main()
{Stack s1;Queue q1;return 0;
}可以看到两个自定义类型的Stack变量都进行了初始化而且调用了Stack的构造函数,如果Stack没有给构造函数那Queue也是随机值了 无参的构造函数和全缺省的构造函数都称为默认构造函数并且默认构造函数只能有一个。注意无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数都可以认为是默认构造函数 2.2.4注意 C11 中针对内置类型成员不初始化的缺陷又打了补丁即内置类型成员变量在类中声明时可以给默认值可以用来对内置类型进行初始化指针都是内置类型Date d1也是* class Stack
{
public://Stack(int capacity 3)//{// _a (int*)malloc(sizeof(int) * capacity);// assert(_a);// _capacity capacity;// _top -1;//}private:int* _anullptr;int _top-1;int _capacity1;//这三个是内置类型
};int main()
{Stack s1;return 0;
}3.析构函数
3.1概念 析构函数与构造函数功能相反析构函数不是完成对对象本身的销毁局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数完成对象中资源的清理工作 3.2特性 析构函数是特殊的成员函数其特征如下 析构函数名是在类名前加上字符 ~。无参数无返回值类型(跟构造函数一样)。一个类只能有一个析构函数。若未显式定义系统会自动生成默认的析构函数。注意析构函数不能重载对象生命周期结束时出了作用域C编译系统系统自动调用析构函数 class Date
{
public://此时没有进行显示构造函数定义会使用系统默认生成的无参构造函数void Print(){cout _year - _month - _day endl;}~Date(){cout 调用了析构函数;}private:int _year1; // 年int _month1; // 月int _day1; // 日
};int main()
{Date d1;d1.Print();return 0;
}关于编译器自动生成的析构函数是否会完成一些事情呢编译器生成的默认析构函数对自定类型成员调用它的析构函数。对内置类型不进行处理 class Time
{
public:~Time(){cout 调用了time的析构函数 endl;}
private:int _hour;int _minute;int _second;
};class Date
{
private:// 基本类型(内置类型)int _year 1;int _month 1;int _day 1;// 自定义类型Time _time;
};int main()
{Date d1;return 0;
}程序运行结束后输出调用了time的析构函数 在main方法中根本没有直接创建Time类的对象为什么最后会调用Time类的析构函数 因为main方法中创建了Date对象d而d中包含4个成员变量其中_year, _month, _day三个是内置类型成员销毁时不需要资源清理最后系统直接将其内存回收即可 而_time是Time类对象所以在 d销毁时要将其内部包含的Time类的_time对象销毁所以要调用Time类的析构函数。但是main函数 中不能直接调用Time类的析构函数实际要释放的是Date类对象所以编译器会调用Date类的析构函数而Date没有显式提供则编译器会给Date类生成一个默认的析构函数目的是在其内部调用Time类的析构函数即当Date对象销毁时要保证其内部每个自定义对象都可以正确销毁 main函数中并没有直接调用Time类析构函数而是显式调用编译器为Date类生成的默认析构函数 注意创建哪个类的对象则调用该类的析构函数销毁那个类的对象则调用该类的析构函数 如果类中没有申请资源时析构函数可以不写直接使用编译器生成的默认析构函数比如Date类有资源申请时一定要写否则会造成资源泄漏(内存泄漏)比如Stack类 好啦这次的内容就先到这里啦期待下次与大家分享
我的博客即将同步至腾讯云开发者社区邀请大家一同入驻https://cloud.tencent.com/developer/support-plan?invite_code1pao3hba2ho4v