C语言中类的六大默认成员函数如何改写为一个长尾词的?

2026-04-12 10:572阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计3163个文字,预计阅读时间需要13分钟。

C语言中类的六大默认成员函数如何改写为一个长尾词的?

目录

一、类的默认成员函数

二、构造函数的定义和返回值

三、构造函数的调用

四、构造函数的重载

五、系统生成的默认构造函数

目录
  • 一、类的默认成员函数
  • 二、构造函数Date(形参列表)
    • 1、构造函数的函数名和返回值
    • 2、构造函数的调用
    • 3、构造函数的重载
    • 4、系统生成的默认构造函数
    • 5、系统生成的默认构造函数的作用
    • 6、可以在内置类型的成员变量的声明中给缺省值
    • 7、初始化列表初始化
    • 8、单参数构造(C++98)、多参数构造(C++11)
  • 三、析构函数~Date()
    • 1、析构函数的函数名、参数和返回值
    • 2、析构函数的特点
    • 3、编译器生成的默认析构函数
  • 四、拷贝构造Date(const Date& d)
    • 五、赋值运算符重载Date& operator=(const Date& d )
      • 六、取地址操作符重载和const取地址操作符重载

        一、类的默认成员函数

        二、构造函数Date(形参列表)

        构造函数主要完成初始化对象,相当于C语言阶段写的Init函数。

        默认构造函数:无参的构造函数或全缺省的构造函数,二者只能存在一个,同时存在类中,调用时会出现二义性。

        1、构造函数的函数名和返回值

        构造函数的函数名和类名相同且无返回值

        2、构造函数的调用

        对象实例化时,编译器自动调用对应的构造函数且只调用一次

        3、构造函数的重载

        构造函数可以重载(多种初始化方式)注意:虽然全缺省和无参的构造函数构成重载,但是调用时存在二义性。

        class Date { public: //构造函数的重载 Date() { } Date(int year,int month,int day) { _year = year; _month = month; _day = day; } private: int _year; int _month; int _day; }; int main() { Date d1;//创建并通过无参构造函数初始化对象时,无需加括号,不然变成了函数声明 Date d2(2022,9,23); return 0; }

        4、系统生成的默认构造函数

        如果我们在类中不写构造函数,C++编译器会在类中帮我们生成一个无参的构造函数。我们写了构造函数,那么系统将不会生成。

        我们构造对象并调用构造函数时,初始化的数据是随机值:

        5、系统生成的默认构造函数的作用

        系统生成默认构造函数对内置类型不处理,对自定义类型调用他的构造函数。

        注意:下方代码中,Date类中的内置类型将会调用Date类中的构造函数;Date类中的Time _t将会调用Time类中的构造函数。

        6、可以在内置类型的成员变量的声明中给缺省值

        C++11中针对内置类型不处理初始化为随机值的问题,打了补丁:内置类型成员变量在类中声明可以给默认值,甚至可以给动态开辟的缺省值,缺点是不能判断空间是否开辟成功。

        注意这里的默认值是缺省值,不是初始化。初始化是要等对象调用时才叫初始化。

        class Date { private: int _year=1; int _month=2; int _day=3; int* arr = (int*)malloc(sizeof(int) * 5); };

        这个特性只能用于解决默认构造函数初始化为随机值的问题。这个特性不能解决对象的多种初始化方式(这也是构造函数支持重载的原因),构造函数该写还是得自己写。

        7、初始化列表初始化

        • 1、对象的每个成员变量是在初始化列表部分进行初始化,而函数体内的行为是对成员函数赋初值。
        • 2、如果没有在初始化列表里显示初始化某个成员函数,对于内置类型,有缺省值用缺省值,无缺省值初始化为随机值;对于自定义类型将会调用它的默认构造函数,没有找到默认构造就会报错。
        • 3、引用、const、无默认构造函数的自定义类型必须通过初始化列表初始化。
        • 4、成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关。

        Date(int year=1,int month=1,int day=1)//缺省值 :_year(year)//成员变量的定义 ,_month(month) ,_day(day) {}//成员变量的赋初值

        总结:尽量使用使用初始化列表进行初始化,在类中尽量提供默认构造函数(最好是全缺省的默认构造函数)

        8、单参数构造(C++98)、多参数构造(C++11)

        class Date { public: 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() { //单参数的构造,构造+拷贝,编译器直接优化为构造C++98 Date d1 = 2022; //临时对象具有常性,构造+拷贝,编译器不会优化 const Date& d2 = 2023; //多参数的构造C++11 Date d3 = { 2022,10,16 }; return 0; }

        • 1、在构造时,支持等号加参数的构造形式,实际上发生的是隐式类型转换。2022由int类型隐式类型转换为Date型的临时对象,该临时对象再将它的值拷贝构造给d1。
        • 2、2023会隐式类型转换为Date类型的临时对象,具有常属性。d2是这个临时对象的引用,所以需要加上const。这里发生构造+拷贝构造,涉及临时对象的引用,所以编译器并不会发生优化。
        • 3、可以使用explicit关键字修饰构造函数,会禁止隐式类型转换。

        三、析构函数~Date()

        析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。资源包括动态开辟的空间,文件的关闭等。相当于C语言阶段写的destroy函数。

        C语言中类的六大默认成员函数如何改写为一个长尾词的?

        1、析构函数的函数名、参数和返回值

        析构函数的函数名是类名前加~,无参无返回值类型。

        2、析构函数的特点

        一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载

        对象生命周期结束时,C++编译系统系统自动调用析构函数

        3、编译器生成的默认析构函数

        对于编译器生成的默认析构函数,对自定义类型调用他的析构函数。对于内置类型,没有需要处理资源。

        注意:Date类中的内置类型会调用Date类中的析构函数;Date类中的自定义类型Time _t会调用Time的析构函数。

        四、拷贝构造Date(const Date& d)

        1、拷贝构造函数是构造函数的重载

        拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

        拷贝构造函数的函数名和构造函数相同无返回值,在参数上和构造函数构成重载。

        2、拷贝构造函数的参数

        拷贝构造函数的参数只有一个并且是类类型对象引用。如果使用传值传参的方式进行拷贝构造,在传值的过程中实参需要拷贝一份数据给形参,这个过程需要调用拷贝构造。形成层层传值引发对象的拷贝的递归(有递无归)调用。

        3、若未显式定义,编译器会生成默认的拷贝构造函数

        默认的构造函数对于内置类型按照字节拷贝。对于自定义类型则调用它的拷贝构造函数。

        4、拷贝构造函数的深浅拷贝

        通过默认的拷贝构造函数构造的对象,按字节完成拷贝。这种拷贝被称为浅拷贝(值拷贝)。

        int main() { Date d1(2022,9,24); Date d2(d1); return 0; }

        对于内置类型,使用浅拷贝即可,系统默认生成的就可以做到,所以我们不用动手写拷贝构造函数。注意这里有d1,d2两个对象,当main函数生命周期结束时,这两个对象均会发生一次析构,d2先析构,d1后析构。(后定义的先销毁,类似栈的后进先出原则)

        但是浅拷贝对于占用“资源”的成员变量时(例如成员变量中有动态开辟或fopen的资源),指针虽然复制了,但是所指向的内容却没有复制,析构时存在同一块空间被释放两次的问题。需要进行深拷贝。深拷贝的拷贝构造函数必须自己手动实现。

        class Stack { public: Stack(int capacity=100)//构造函数 { _capacity = capacity; _top = 0; _arr = (int*)malloc(sizeof(int) * 5); if (_arr == nullptr) { perror("malloc fail"); exit(-1); } } //Stack(const Stack& st)//浅拷贝,栈这个类不能用浅拷贝 //{ // _capacity = st._capacity; // _top = st._top; // _arr = st._arr; //} Stack(const Stack& st)//深拷贝 { _capacity = st._capacity; _top = st._top; _arr = (int*)malloc(sizeof(int) * st._top); if (_arr == nullptr) { perror("malloc fail"); exit(-1); } memcpy(_arr, st._arr,sizeof(int)*st._top); } ~Stack()//析构函数 { _capacity = 0; _top = 0; free(_arr); _arr = nullptr; } private: int* _arr; int _top; int _capacity; };

        栈这个类因为成员变量中有动态开辟的空间,所以要用深拷贝。

        5、拷贝构造函数调用场景

        • 1、使用已存在的对象创建新对象
        • 2、函数参数类型为类的类型对象(传值调用,实参拷贝给形参)
        • 3、函数返回值类型为类的良心对象(传值返回)

        五、赋值运算符重载Date& operator=(const Date& d )

        1、赋值运算符重载

        只有赋值运算符是默认成员函数。

        2、赋值运算符重载的注意事项

        • 1、参数是const T&,传引用可以减少一次拷贝构造。
        • 2、返回值是*this的引用,引用返回,减少一次拷贝构造,有返回值是为了支持函数的链式访问。
        • 3、务必检查下是否支持自己给自己赋值。
        • 4、赋值运算符重载必须是类中的默认成员函数,不能写在全局。
        • 5、系统默认生成的赋值运算符重载会完成值拷贝。

        六、取地址操作符重载和const取地址操作符重载

        Date* operator&() { return this; //return nullptr; } const Date* operator&()const { return this; //return nullptr; }

        不用自己写,除非想让别人通过取地址操作符获取到特定值(自己在重载函数内部写)或屏蔽类地址。

        以上就是详解C++中类的六大默认成员函数的详细内容,更多关于C++类成员函数的资料请关注自由互联其它相关文章!

        本文共计3163个文字,预计阅读时间需要13分钟。

        C语言中类的六大默认成员函数如何改写为一个长尾词的?

        目录

        一、类的默认成员函数

        二、构造函数的定义和返回值

        三、构造函数的调用

        四、构造函数的重载

        五、系统生成的默认构造函数

        目录
        • 一、类的默认成员函数
        • 二、构造函数Date(形参列表)
          • 1、构造函数的函数名和返回值
          • 2、构造函数的调用
          • 3、构造函数的重载
          • 4、系统生成的默认构造函数
          • 5、系统生成的默认构造函数的作用
          • 6、可以在内置类型的成员变量的声明中给缺省值
          • 7、初始化列表初始化
          • 8、单参数构造(C++98)、多参数构造(C++11)
        • 三、析构函数~Date()
          • 1、析构函数的函数名、参数和返回值
          • 2、析构函数的特点
          • 3、编译器生成的默认析构函数
        • 四、拷贝构造Date(const Date& d)
          • 五、赋值运算符重载Date& operator=(const Date& d )
            • 六、取地址操作符重载和const取地址操作符重载

              一、类的默认成员函数

              二、构造函数Date(形参列表)

              构造函数主要完成初始化对象,相当于C语言阶段写的Init函数。

              默认构造函数:无参的构造函数或全缺省的构造函数,二者只能存在一个,同时存在类中,调用时会出现二义性。

              1、构造函数的函数名和返回值

              构造函数的函数名和类名相同且无返回值

              2、构造函数的调用

              对象实例化时,编译器自动调用对应的构造函数且只调用一次

              3、构造函数的重载

              构造函数可以重载(多种初始化方式)注意:虽然全缺省和无参的构造函数构成重载,但是调用时存在二义性。

              class Date { public: //构造函数的重载 Date() { } Date(int year,int month,int day) { _year = year; _month = month; _day = day; } private: int _year; int _month; int _day; }; int main() { Date d1;//创建并通过无参构造函数初始化对象时,无需加括号,不然变成了函数声明 Date d2(2022,9,23); return 0; }

              4、系统生成的默认构造函数

              如果我们在类中不写构造函数,C++编译器会在类中帮我们生成一个无参的构造函数。我们写了构造函数,那么系统将不会生成。

              我们构造对象并调用构造函数时,初始化的数据是随机值:

              5、系统生成的默认构造函数的作用

              系统生成默认构造函数对内置类型不处理,对自定义类型调用他的构造函数。

              注意:下方代码中,Date类中的内置类型将会调用Date类中的构造函数;Date类中的Time _t将会调用Time类中的构造函数。

              6、可以在内置类型的成员变量的声明中给缺省值

              C++11中针对内置类型不处理初始化为随机值的问题,打了补丁:内置类型成员变量在类中声明可以给默认值,甚至可以给动态开辟的缺省值,缺点是不能判断空间是否开辟成功。

              注意这里的默认值是缺省值,不是初始化。初始化是要等对象调用时才叫初始化。

              class Date { private: int _year=1; int _month=2; int _day=3; int* arr = (int*)malloc(sizeof(int) * 5); };

              这个特性只能用于解决默认构造函数初始化为随机值的问题。这个特性不能解决对象的多种初始化方式(这也是构造函数支持重载的原因),构造函数该写还是得自己写。

              7、初始化列表初始化

              • 1、对象的每个成员变量是在初始化列表部分进行初始化,而函数体内的行为是对成员函数赋初值。
              • 2、如果没有在初始化列表里显示初始化某个成员函数,对于内置类型,有缺省值用缺省值,无缺省值初始化为随机值;对于自定义类型将会调用它的默认构造函数,没有找到默认构造就会报错。
              • 3、引用、const、无默认构造函数的自定义类型必须通过初始化列表初始化。
              • 4、成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关。

              Date(int year=1,int month=1,int day=1)//缺省值 :_year(year)//成员变量的定义 ,_month(month) ,_day(day) {}//成员变量的赋初值

              总结:尽量使用使用初始化列表进行初始化,在类中尽量提供默认构造函数(最好是全缺省的默认构造函数)

              8、单参数构造(C++98)、多参数构造(C++11)

              class Date { public: 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() { //单参数的构造,构造+拷贝,编译器直接优化为构造C++98 Date d1 = 2022; //临时对象具有常性,构造+拷贝,编译器不会优化 const Date& d2 = 2023; //多参数的构造C++11 Date d3 = { 2022,10,16 }; return 0; }

              • 1、在构造时,支持等号加参数的构造形式,实际上发生的是隐式类型转换。2022由int类型隐式类型转换为Date型的临时对象,该临时对象再将它的值拷贝构造给d1。
              • 2、2023会隐式类型转换为Date类型的临时对象,具有常属性。d2是这个临时对象的引用,所以需要加上const。这里发生构造+拷贝构造,涉及临时对象的引用,所以编译器并不会发生优化。
              • 3、可以使用explicit关键字修饰构造函数,会禁止隐式类型转换。

              三、析构函数~Date()

              析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。资源包括动态开辟的空间,文件的关闭等。相当于C语言阶段写的destroy函数。

              C语言中类的六大默认成员函数如何改写为一个长尾词的?

              1、析构函数的函数名、参数和返回值

              析构函数的函数名是类名前加~,无参无返回值类型。

              2、析构函数的特点

              一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载

              对象生命周期结束时,C++编译系统系统自动调用析构函数

              3、编译器生成的默认析构函数

              对于编译器生成的默认析构函数,对自定义类型调用他的析构函数。对于内置类型,没有需要处理资源。

              注意:Date类中的内置类型会调用Date类中的析构函数;Date类中的自定义类型Time _t会调用Time的析构函数。

              四、拷贝构造Date(const Date& d)

              1、拷贝构造函数是构造函数的重载

              拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

              拷贝构造函数的函数名和构造函数相同无返回值,在参数上和构造函数构成重载。

              2、拷贝构造函数的参数

              拷贝构造函数的参数只有一个并且是类类型对象引用。如果使用传值传参的方式进行拷贝构造,在传值的过程中实参需要拷贝一份数据给形参,这个过程需要调用拷贝构造。形成层层传值引发对象的拷贝的递归(有递无归)调用。

              3、若未显式定义,编译器会生成默认的拷贝构造函数

              默认的构造函数对于内置类型按照字节拷贝。对于自定义类型则调用它的拷贝构造函数。

              4、拷贝构造函数的深浅拷贝

              通过默认的拷贝构造函数构造的对象,按字节完成拷贝。这种拷贝被称为浅拷贝(值拷贝)。

              int main() { Date d1(2022,9,24); Date d2(d1); return 0; }

              对于内置类型,使用浅拷贝即可,系统默认生成的就可以做到,所以我们不用动手写拷贝构造函数。注意这里有d1,d2两个对象,当main函数生命周期结束时,这两个对象均会发生一次析构,d2先析构,d1后析构。(后定义的先销毁,类似栈的后进先出原则)

              但是浅拷贝对于占用“资源”的成员变量时(例如成员变量中有动态开辟或fopen的资源),指针虽然复制了,但是所指向的内容却没有复制,析构时存在同一块空间被释放两次的问题。需要进行深拷贝。深拷贝的拷贝构造函数必须自己手动实现。

              class Stack { public: Stack(int capacity=100)//构造函数 { _capacity = capacity; _top = 0; _arr = (int*)malloc(sizeof(int) * 5); if (_arr == nullptr) { perror("malloc fail"); exit(-1); } } //Stack(const Stack& st)//浅拷贝,栈这个类不能用浅拷贝 //{ // _capacity = st._capacity; // _top = st._top; // _arr = st._arr; //} Stack(const Stack& st)//深拷贝 { _capacity = st._capacity; _top = st._top; _arr = (int*)malloc(sizeof(int) * st._top); if (_arr == nullptr) { perror("malloc fail"); exit(-1); } memcpy(_arr, st._arr,sizeof(int)*st._top); } ~Stack()//析构函数 { _capacity = 0; _top = 0; free(_arr); _arr = nullptr; } private: int* _arr; int _top; int _capacity; };

              栈这个类因为成员变量中有动态开辟的空间,所以要用深拷贝。

              5、拷贝构造函数调用场景

              • 1、使用已存在的对象创建新对象
              • 2、函数参数类型为类的类型对象(传值调用,实参拷贝给形参)
              • 3、函数返回值类型为类的良心对象(传值返回)

              五、赋值运算符重载Date& operator=(const Date& d )

              1、赋值运算符重载

              只有赋值运算符是默认成员函数。

              2、赋值运算符重载的注意事项

              • 1、参数是const T&,传引用可以减少一次拷贝构造。
              • 2、返回值是*this的引用,引用返回,减少一次拷贝构造,有返回值是为了支持函数的链式访问。
              • 3、务必检查下是否支持自己给自己赋值。
              • 4、赋值运算符重载必须是类中的默认成员函数,不能写在全局。
              • 5、系统默认生成的赋值运算符重载会完成值拷贝。

              六、取地址操作符重载和const取地址操作符重载

              Date* operator&() { return this; //return nullptr; } const Date* operator&()const { return this; //return nullptr; }

              不用自己写,除非想让别人通过取地址操作符获取到特定值(自己在重载函数内部写)或屏蔽类地址。

              以上就是详解C++中类的六大默认成员函数的详细内容,更多关于C++类成员函数的资料请关注自由互联其它相关文章!