建立网站企业抚顺市营商环境建设局网站
- 作者: 五速梦信息网
- 时间: 2026年03月21日 10:46
当前位置: 首页 > news >正文
建立网站企业,抚顺市营商环境建设局网站,dw设计模板,网站项目怎么做的个人主页点击直达#xff1a;小白不是程序媛
C系列专栏#xff1a;C头疼记 目录
前言
类的6个默认成员函数
构造函数
概念
构造函数的特性
析构函数
概念
析构函数特性
拷贝构造函数
概念
拷贝构造函数特性
总结 前言
上篇文章我们对于C中的类有了初步的认识和…
个人主页点击直达小白不是程序媛
C系列专栏C头疼记 目录
前言
类的6个默认成员函数
构造函数
概念
构造函数的特性
析构函数
概念
析构函数特性
拷贝构造函数
概念
拷贝构造函数特性
总结 前言
上篇文章我们对于C中的类有了初步的认识和了解在最后通过日期类的类型对于this指针有了一定的了解今天我们继续深入C类和对象的了解 类的6个默认成员函数
如果一个类中什么成员都没有简称为空类。 空类中真的什么都没有吗并不是任何类在什么都不写时编译器会自动生成以下6个默认成员 函数。默认成员函数用户没有显式实现编译器会生成的成员函数称为默认成员函数。
class Date { }; 构造函数 概念
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, 27);d1.Print();return 0;
} 对于Date类可以通过 Init 公有方法给对象设置日期但如果每次创建对象时都调用该方法设置 信息未免有点麻烦那能否在对象创建时就将信息设置进去呢构造函数是一个特殊的成员函数名字与类名相同,创建类类型对象时由编译器自动调用以保证每个数据成员都有 一个合适的初始值并且在对象整个生命周期内只调用一次。 构造函数的特性
构造函数是特殊的成员函数需要注意的是构造函数虽然名称叫构造但是构造函数的主要任 务并不是开空间创建对象而是初始化对象。 其特征如下 1. 函数名与类名相同。 2. 无返回值。 3. 对象实例化时编译器自动调用对应的构造函数。 4. 构造函数可以重载。 //构造函数
class Date
{
public://无参构造函数Date(){_year 1;_month 1;_day 1;}//有参构造函数//重载//缺省Date(int year 1, int month 1, int day 1){_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(2023, 10, 27);d2.Print();return 0;
}
注意如果通过无参构造函数创建对象时对象后面不用跟括号否则就成了函数声明 5. 如果类中没有显式定义构造函数则C编译器会自动生成一个无参的默认构造函数一旦用户显式定义编译器将不再生成。 class Date
{
public:/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;
}
将Date类中构造函数屏蔽后代码可以通过编译因为编译器生成了一个无参的默认构造函数 6. 关于编译器生成的默认成员函数很多童鞋会有疑惑不实现构造函数的情况下编译器会生成默认的构造函数。但是看起来默认构造函数又没什么用d对象调用了编译器生成的默 认构造函数但是d对象_year/_month/_day依旧是随机值。也就说在这里编译器生成的默认构造函数并没有什么用 解答C把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类 型如int/char…自定义类型就是我们使用class/struct/union等自己定义的类型看看 下面的程序就会发现编译器生成默认的构造函数会对自定类型成员_t调用的它的默认成员 函数。 class Time
{
public:Time(){_hour 1;_minute 1;_secend 1;}void Print(){cout _hour - _minute - _secend endl;}
private:int _hour;int _minute;int _secend;
};
class Date
{void Print(){cout _year - _month - _day endl;}
private://内置类型int _year;int _month;int _day;//自定义类型Time _t;
};
int main()
{Date d1;return 0;
}注意C11 中针对内置类型成员不初始化的缺陷又打了补丁即内置类型成员变量在 类中声明时可以给默认值。
class Time
{
public:Time(){_hour 1;_minute 1;_secend 1;}void Print(){cout _hour - _minute - _secend endl;}
private:int _hour;int _minute;int _secend;
};
class Date
{void Print(){cout _year - _month - _day endl;}
private://内置类型int _year1;int _month1;int _day1;//自定义类型Time _t;
};
int main()
{Date d1;return 0;
}7. 无参的构造函数和全缺省的构造函数都称为默认构造函数并且默认构造函数只能有一个。注意无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数都可以认为 是默认构造函数。 析构函数 概念
通过前面构造函数的学习我们知道一个对象是怎么来的那一个对象又是怎么没呢的析构函数与构造函数功能相反析构函数不是完成对对象本身的销毁局部对象销毁工作是由 编译器完成的。而对象在销毁时会自动调用析构函数完成对象中资源的清理工作。
class stack
{
public:stack(int capacity 3){_a (int*)malloc(sizeof(int) * capacity);if (nullptr _a){perror(malloc fail);exit(-1);}_capacity capacity;_top 0;}void Destory(){free(_a);_capacity 0;_top 0;}
private:int* _a;int _capacity;int _top;
};int main()
{stack s1;return 0;
}析构函数特性 析构函数是特殊的成员函数其特征如下 1. 析构函数名是在类名前加上字符 ~。 2. 无参数无返回值类型。 3. 一个类只能有一个析构函数。若未显式定义系统会自动生成默认的析构函数。注意析构函数不能重载 4. 对象生命周期结束时C编译系统系统自动调用析构函数。 class stack
{
public:stack(int capacity 3){_a (int*)malloc(sizeof(int) * capacity);if (nullptr _a){perror(malloc fail);exit(-1);}_capacity capacity;_top 0;}~stack(){free(_a);_capacity 0;_top 0;}
private:int* _a;int _capacity;int _top;
};int main()
{stack s1;return 0;
}5. 关于编译器自动生成的析构函数是否会完成一些事情呢下面的程序我们会看到编译器生成的默认析构函数对自定类型成员调用它的析构函数。 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;
}
程序运行结束后输出~Time() 在main方法中根本没有直接创建Time类的对象为什么最后会调用Time类的析构函数 因为main方法中创建了Date对象d而d中包含4个成员变量其中_year, _month,_day三个是内置类型成员销毁时不需要资源清理最后系统直接将其内存回收即可而_t是Time类对象所以在d销毁时要将其内部包含的Time类的_t对象销毁所以要调用Time类的析构函数。但是main函数中不能直接调用Time类的析构函数实际要释放的是Date类对象所以编译器会调用Date 类的析构函数而Date没有显式提供则编译器会给Date类生成一个默认的析构函数目的是在其内部调用Time类的析构函数即当Date对象销毁时要保证其内部每个自定义对象都可以正确销毁main函数中并没有直接调用Time类析构函数而是显式调用编译器为Date类生成的默认析构函数注意创建哪个类的对象则调用该类的析构函数销毁那个类的对象则调用该类的析构函数 6. 如果类中没有申请资源时析构函数可以不写直接使用编译器生成的默认析构函数比如Date类有资源申请时一定要写否则会造成资源泄漏比如Stack类。 拷贝构造函数 概念
在现实生活中可能存在一个与你一样的自己我们称其为双胞胎。
那在创建对象时可否创建一个与已存在对象一某一样的新对象呢拷贝构造函数只有单个形参该形参是对本类类型对象的引用(一般常用const修饰)在用已存 在的类类型对象创建新对象时由编译器自动调用。 拷贝构造函数特性 拷贝构造函数也是特殊的成员函数其特征如下 1. 拷贝构造函数是构造函数的一个重载形式。 2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用使用传值方式编译器直接报错因为会引发无穷递归调用。 class Date
{
public :Date(){_year 1;_month 1;_day 1;}Date(const Date d){_year d._year;_month d._month;_day d._day;cout 拷贝构造函数的调用 endl;}
private :int _year;int _month;int _day;
};int main()
{Date d1;Date d2(d1);return 0;
} 3. 若未显式定义编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按 字节序完成拷贝这种拷贝叫做浅拷贝或者值拷贝。
class Time
{
public:Time(){_hour 1;_minute 1;_secend 1;}Time(const Time T){_hour T._hour;_minute T._minute;_secend T._secend;cout Time拷贝构造的调用 endl;}void Print(){cout _hour - _minute - _secend endl;}
private:int _hour;int _minute;int _secend;
};
class Date
{
public:void Print(){cout _year - _month - _day endl;}
private:int _year2023;int _month10;int _day27;Time _t;
};
int main()
{Date d1;Date d2(d1);return 0;
} 注意在编译器生成的默认拷贝构造函数中内置类型是按照字节方式直接拷贝的而自定 义类型是调用其拷贝构造函数完成拷贝的。 4. 编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了还需要自己显式实现吗 当然像日期类这样的类是没必要的。那么下面的类呢验证一下试试
class stack
{
public:stack(int capacity 3){_a (int*)malloc(sizeof(int) * capacity);if (nullptr _a){perror(malloc fail);}_capacity capacity;this-_top 0;}stack(const stack stt){_a stt._a;_capacity stt._capacity;_top stt._top;}~stack(){free(_a);this-_a nullptr;this-_capacity 0;this-_top 0;}
private :int* _a;int _capacity;int _top;
};class MyQueue
{stack _pushstack;stack _popshtack;
};
int main()
{MyQueue q1;MyQueue q2(q1);return 0;
} 注意类中如果没有涉及资源申请时拷贝构造函数是否写都可以一旦涉及到资源申请 时则拷贝构造函数是一定要写的否则就是浅拷贝。 该如何解决这个问题呢我给出一段代码
class stack
{
public:stack(int capacity 3){_a (int*)malloc(sizeof(int) * capacity);if (nullptr _a){perror(malloc fail);}_capacity capacity;this-_top 0;}stack(const stack stt){this-_a (int*)malloc(sizeof(int) * stt._capacity);if (nullptr _a){perror(malloc fail);}memcpy(this-_a, stt._a, sizeof(int) * stt._top);this-_capacity stt._capacity;this-_top stt._top;}~stack(){free(_a);this-_a nullptr;this-_capacity 0;this-_top 0;}
private:int* _a;int _capacity;int _top;
};class MyQueue
{stack _pushstack;stack _popshtack;
};
int main()
{MyQueue q1;MyQueue q2(q1);return 0;
} 深拷贝本质拷贝指向的资源让我跟你有一样大的空间一样的值 5. 拷贝构造函数典型调用场景 使用已存在对象创建新对象函数参数类型为类类型对象函数返回值类型为类类型对象 为了提高程序效率一般对象传参时尽量使用引用类型返回时根据实际场景能用引用 尽量使用引用。 总结 构造函数对于自定义类型会调用其构造函数对于内置类型 不做任何处理在C11中内置类型在类里可以初始化析构函数对于自定义类型会调用其析构函数对于内置类型销毁时不需要资源清理最后系统直接将其内存回收即可拷贝构造函数对于自定义类型调用其拷贝构造函数对于内置类型完成值拷贝 今天的文章就到这里就结束了希望大家看完有所收获也希望大家留言指出我文章中出现的内容同时也感谢各位看官的三连支持你们的支持就是我更新的动力 下篇预告赋值重载和取地址重载
- 上一篇: 建立网站解析会员视频是犯什么罪适合中层管理的培训
- 下一篇: 建立网站容量国外服务器厂商
相关文章
-
建立网站解析会员视频是犯什么罪适合中层管理的培训
建立网站解析会员视频是犯什么罪适合中层管理的培训
- 技术栈
- 2026年03月21日
-
建立网站接受投注是什么意思网站功能调研
建立网站接受投注是什么意思网站功能调研
- 技术栈
- 2026年03月21日
-
建立网站基本步骤广西建设厅网证件查询
建立网站基本步骤广西建设厅网证件查询
- 技术栈
- 2026年03月21日
-
建立网站容量国外服务器厂商
建立网站容量国外服务器厂商
- 技术栈
- 2026年03月21日
-
建立网站容量图书馆网页设计素材
建立网站容量图书馆网页设计素材
- 技术栈
- 2026年03月21日
-
建立网站如何规划和实施建设阳江市网络问政
建立网站如何规划和实施建设阳江市网络问政
- 技术栈
- 2026年03月21日
