ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

C++ 类与对象(二)(1.构造析构函数)

C++ 类与对象(二)(1.构造析构函数) 目录类的默认成员函数构造析构函数1.构造函数2.拷贝构造函数3.析构函数类的默认成员函数在书写构造类的时候除了我们所写的成员函数之外如果没有编写对应的默认函数编译器会默认生成对应的6个默认函数比较重要的前4个函数。补充在C11以后多了2个默认函数移动构造和移值构造为什么要写默认成员函数原因编译器的提供的默认成员函数对于我们程序员来说可能不是想要的不同情况编译器提供的默认成员函数不适配需要进行修改。构造析构函数1.构造函数在原先用C语言写Stack等数据结构中每次都需要Init函数来进行初始化在每次都有可能我们忘记进行初始化导致系统报错的可能所以在C中构造函数就为了解决这个问题的在每次实例化对象的时候都会进行调用构造函数进行初始化。构造函数的特点及要求函数名与类名同名。无返回值。在C 中构造函数可以不用写void对象实例化后自动调用构造函数。构造函数可以重载遵循重载规则。用户没有构造函数编译器自动生成如果有就不会生成就用用户自己的构造函数。无参构造或者、全缺省构造函、编译自动生成的构造函数都叫构造函数。三个函数只能存在一个不能同时出现。前两存在的时候会导致无参和缺省构造导致分歧。日期类的构造函数全缺省写法//Date.h #pragma once #include iostream #include stdlib.h #include stdbool.h #include assert.h using namespace std; class Date { public: Date(int year 1, int month 1, int day 1); void Print(); private: int _year; int _month; int _day; };//Date.cpp #define _CRT_SECURE_NO_WARNINGS #include Data.h Date::Date(int year, int month, int day) { _year year; _month month; _day day; } void Date::Print() { cout _year / _month / _day endl; } int main() { Date adt(2026, 8, 8); adt.Print(); return 0; }无参和带参写法Date() { _year 1; _month 1; _day 1; } Date(int year, int month, int day) { _year year; _month month; _day day; }很明显的看到全缺省的优势就体现出来了而却这种带参写法还是有问题如果只写年份不写其他的内容一样会导致报错。2.拷贝构造函数定义如果已经有一个相同类的实例化对象可以通过拷贝该对象实例化一个所以成员变量一致的对象这就是拷贝构造函数也就是是一个特殊的狗制造函数。拷贝构造函数要求及其特点拷贝构造函数是构造函数的重载。拷贝构造函数必须第一个类型是类类型的对象的引用如果使用的是类类型会导无限递归报错拷贝构造函数也可以多个参数但第一个一定是类类型的引用后面必须有缺省参数。C规定了自定义类型对象进行时必须用拷贝构造所以这里的自定义类型传参值和返回值都会调用拷贝构造完成。若没有拷贝构造函数编译器也会自动生成对于的拷贝构造函数。与我们所写的拷贝构造不同编译器默认拷贝构造是通过一个字节一个字节经行的拷贝。学习拷贝构造的原因像Date 类这种内存偏简单的类编译器默认的拷贝构造就够用但是 Stack 栈这种需要申请空间等复杂的内容编译器生成的默认拷贝构造就不能满足我们的需求所以需要自定义拷贝构造自己需要自己搞。为什么要拷贝构一定第一个是类类型的应用传值会产生临时对象调用拷贝构造传值引用返回返回的是返回对象的别名应用没有产生拷贝。Data::Data(const Data data) { _year data._year; _month data._month; _day data._day; } Date::Date(const Date* d) { _year d-_year; _month d-_month; _day d-_day; }3.析构函数析构函数就是在实例化对象在生命周期末的时候会调用通常析构函数会使用在空间销毁上像Stack栈的空间释放就可以使用到析构函数代替Destory函数的作用防止在我们忘记对空间释放时自动调用与构造函数的特点一致除了只会在生命周期结束时会使用也不需要 void 做返回值与构造不同就是在原先类名之前加一个“ ~ ”。Date::~Date() { //... };typedef int STDataType; class Stack { public: // 构造函数 Stack(int n 4) { _a (STDataType*)malloc(sizeof(STDataType) * n); if (nullptr _a) { perror(malloc); exit(1); } _capacity n; _top 0; } // 拷贝构造函数 Stack(Stack s) { _a (STDataType*)malloc(sizeof(STDataType) * s._capacity); if (nullptr _a) { perror(malloc); exit(1);; } memcpy(_a,s._a,sizeof(STDataType)*s._top); _capacity s._capacity; _top s.top; } // 析构函数 ~Stack() { cout ~Stack() endl; free(_a); _a nullptr; _top _capacity 0; } private: STDataType* _a; // 动态数组 size_t _capacity; // 容量 size_t _top; // 栈顶下标0代表空栈 };析构函数调用顺序在初始化多个实例化对象析构函数的调用也是有顺序的析构函数调用顺序类似栈会先调用最后实例化对象。
返回列表