当前位置: 首页 > article >正文

学习记录——day40- 类中特殊的成员函数

一、类中提供的特殊成员函数

构造函数、析构函数、拷贝构造函数、拷贝复制函数、移动构造函数、移动复值函数、取地址运算符重载

        如果用户不显性定义这些函数,系统也会提供指向函数,如果用户显性定义了这些函数,系统就不会提供了。

        这些函数无论是系统提供还是用户定义,都不需要手动调用,特殊时机,系统自动调用

二、构造函数

        使用类去实例化对象时,为对象进行资源的申请以及初始化使用的

1、构造函数相关概念

1、构造函数没有返回值(不是 void ,单纯没有)
2、函数名与类同名
3、访问权限,一般为public
4、类名(形参列表){函数体内容}

 2、调用时机:当使用类实例化对象时,系统自动调用

1、栈区空间:使用类实例化对象时,系统自动调用

                类名 变量名(实参); //此时就调用的构造函数

2、堆区空间:只有在使用new申请空间时,自动调用构造函数

                类名 *指针名;                 //此时仅仅只是定义一个指针变量,并没有为对象分配空间

                指针名 = new 类名(实参); //此时调用的构造函数

#include <iostream>


using namespace std;


class Stu
{
public:
    Stu()
    {
        cout<<"Stu的构造函数"<<endl;
    }
};




int main()
{
    //在栈区申请对象空间
    Stu s1;


    //堆区空间申请对象
    Stu *ptr;          //此时不调用构造函数
    ptr = new Stu;      //此时调用构造函数


    return 0;
}

3、构造函数定义相关

1)构造函数分为有参构造和无参构造函数,有参构造函数可以为成员属性进行初始化,这些构造函数之间构成重载关系

2)一个类中可以有多个构造函数,每个对象仅仅只会调用一个构造函数

3)如果类中没有定义构造函数,那么,系统会自动提供一个无参构造函数,用于对对象空间的申请,如果程序员自己定义了构造函数,系统就不再提供那个无参构造了,如果还想使用无参构造,需要自己定义一个无参构造

#include <iostream>


using namespace std;


class Stu
{
private:
    string name;
    int age;
    double score;


public:
    //无参构造
    Stu()
    {
        cout<<"Stu的无参构造函数"<<endl;
    }
    //自定义有参构造
    Stu(string n, int a)
    {
        this->name = n;
        this->age = a;
        cout<<"Stu::有参构造"<<endl;
    }


    void show()
    {
        cout<<"name = "<<name<<endl;
        cout<<"age = "<<age<<endl;
        cout<<"score = "<<score<<endl;
    }
};




int main()
{
    //在栈区申请对象空间
    Stu s1;                       //此时调用了无参构造,只为对象申请了空间,但是没有为对象初始化
    s1.show();
    cout<<"**************************************"<<endl;


    //申请一个对象,调用有参构造
    Stu s2("zhangsan", 18);          //此时调用了有参构造
    s2.show();
    cout<<"**************************************"<<endl;


    //堆区空间申请对象
    Stu *ptr;          //此时不调用构造函数
    ptr = new Stu;      //此时调用构造函数


    return 0;
}

4、构造函数初始化

使用方式:

        类名(形参1,形参2,。。。形参n):成员1(形参1),成员2(形参2)......成员n(形参n)

{函数体内容}

说明:在构造函数的小括号后,由冒号引出初始化列表,括号外时成员变量,括号内是形参

#include <iostream>


using namespace std;


class Stu
{
private:
    string name;
    int age;
    double score;


public:
    //无参构造
    Stu()
    {
        cout<<"Stu的无参构造函数"<<endl;
    }
    //自定义有参构造
    Stu(string n, int a)
    {
        this->name = n;         //对成员的赋值操作
        this->age = a;
        cout<<"Stu::有参构造1"<<endl;
    }


    //定义有参构造:使用初始化列表完成对成员的初始化工作
    Stu(string n, int a, double s):name(n),age(a),score(s)
    {
        cout<<"Stu::有参构造2"<<endl;
    }


    void show()
    {
        cout<<"name = "<<name<<endl;
        cout<<"age = "<<age<<endl;
        cout<<"score = "<<score<<endl;
    }
};




int main()
{
    //在栈区申请对象空间
    Stu s1;                       //此时调用了无参构造,只为对象申请了空间,但是没有为对象初始化
    s1.show();
    cout<<"**************************************"<<endl;


    //申请一个对象,调用有参构造
    Stu s2("zhangsan", 18);          //此时调用了有参构造
    s2.show();
    cout<<"**************************************"<<endl;




    //申请一个对象,调用有参构造
    Stu s3("lisi", 20, 99.8);
    s3.show();
    cout<<"**************************************"<<endl;




    //堆区空间申请对象
    Stu *ptr;          //此时不调用构造函数
    ptr = new Stu;      //此时调用构造函数


    return 0;
}

5、必须使用初始化列表的情况

1)当构造函数的形参名和成员变量名同名时,可以使用初始化列表来解决

2)当类中有const修饰的成员变量时,对该变量也必须进行初始化,使用初始化列表解决

3)当类中有引用成员时,对该成员的操作也必须使用初始化列表完成

4)当类中有其他类的成员子对象时,对该成员的操作也必须使用初始化列表完成,如果没有使用初始化列表调用有参构造,则系统会自动调用成员子对象的无参构造

#include <iostream>


using namespace std;


class Toy
{
public:
    Toy() {cout<<"Toy::无参构造"<<endl;}
    Toy(string n):name(n) {cout<<"Toy::有参构造"<<endl;}


private:
    string name;


};






class Stu
{
private:
    string name;
    int age;
    double score;
    const int value;        //类中有const类型的成员
    int &key;             //类中有引用成员
    Toy t;               //类中有其他类的成员子对象


public:
    //无参构造
    Stu():value(1314), key(*(new int(520))), t("hello kity")
    {


        cout<<"Stu的无参构造函数"<<endl;
    }
    //自定义有参构造
    Stu(string n, int a, int &k):value(1314), key(k)
    {
        this->name = n;         //对成员的赋值操作
        this->age = a;
        cout<<"Stu::有参构造1"<<endl;
    }


    //定义有参构造:使用初始化列表完成对成员的初始化工作
    Stu(string name, int age, double score, int &k):name(name),age(age),score(score),value(1314),key(k)
    {
        cout<<"Stu::有参构造2"<<endl;
    }


    void show()
    {
        cout<<"name = "<<name<<endl;
        cout<<"age = "<<age<<endl;
        cout<<"score = "<<score<<endl;
    }
};


int main()
{
    //在栈区申请对象空间
    Stu s1;                       //此时调用了无参构造,只为对象申请了空间,但是没有为对象初始化
    s1.show();
    cout<<"**************************************"<<endl;

    //堆区空间申请对象
    Stu *ptr;          //此时不调用构造函数
    ptr = new Stu;      //此时调用构造函数

    return 0;
}

三、析构函数

        功能:在对象消亡时,用于给对象回收空间使用的

1、析构函数相关概念

1)没有返回值(不是 void ,就是没有)

2)函数名:类名前加个波浪线 ~类名

3)权限:一般为public

4)没有参数,所以,一个类中只有一个析构函数,不能进行重载

5)格式: ~类名()

 2、调用时机:当对象的生命周期结束后,用于回收内存空间

        栈区:当栈空间释放后,系统会自动调用该类的析构函数

        堆区:当使用delete关键字释放对象空间时,系统自动调用

3、如果没有手动定义析构函数,系统会提供一个析构函数,用于回收类对象的空间,如果手动定义了析构函数,那么,系统就不再提供默认的析构函数了

4、析构函数示例

#include <iostream>


using namespace std;


class Toy
{
public:
    Toy() {cout<<"Toy::无参构造"<<endl;}
    Toy(string n):name(n) {cout<<"Toy::有参构造"<<endl;}


private:
    string name;


};






class Stu
{
private:
    string name;
    int age;
    double score;
    const int value;        //类中有const类型的成员
    int &key;             //类中有引用成员
    Toy t;               //类中有其他类的成员子对象
    int *ptr;         //指针成员


public:
    //无参构造
    Stu():value(1314), key(*(new int(520))), t("hello kity"), ptr(new int(666))
    {


        cout<<"Stu的无参构造函数"<<endl;
    }
    //自定义有参构造
    Stu(string n, int a, int &k):value(1314), key(k)
    {
        this->name = n;         //对成员的赋值操作
        this->age = a;
        cout<<"Stu::有参构造1"<<endl;
    }


    //定义有参构造:使用初始化列表完成对成员的初始化工作
    Stu(string name, int age, double score, int &k):name(name),age(age),score(score),value(1314),key(k)
    {
        cout<<"Stu::有参构造2"<<endl;
    }


    void show()
    {
        cout<<"name = "<<name<<endl;
        cout<<"age = "<<age<<endl;
        cout<<"score = "<<score<<endl;
    }


    //定义析构函数
    ~Stu()
    {
        delete ptr;          //释放指针的空间
        cout<<"STU::析构函数"<<endl;
    }
};




int main()
{
    //在栈区申请对象空间
    Stu s1;                       //此时调用了无参构造,只为对象申请了空间,但是没有为对象初始化
    s1.show();
    cout<<"**************************************"<<endl;




    //堆区空间申请对象
    Stu *ptr;          //此时不调用构造函数
    ptr = new Stu;      //此时调用构造函数


    //释放ptr的空间
    delete ptr;       //此时会调用析构函数


    return 0;
}

作业

#include <iostream>
#include<cstring>

using namespace std;

class myString
{
    private:
        char *str;          //记录c风格的字符串
        int size;            //记录字符串的实际长度
    public:
        //无参构造
        myString():size(10)
        {
            str = new char[size];         //构造出一个长度为10的字符串                    
        }
        //有参构造
        myString(const char *s);              //有参构造     string  s("hello wirld");
        //判空函数
        bool empty();
        //size函数
        int my_size();
        //length
        int my_length();
        //c_str函数
        char* my_str();
        //at函数
        char& at(int index);        
        //二倍扩容
        bool expend();
};

int main()
{
    cout << "Hello World!" << endl;
    return 0;
}

myString::myString(const char *s)
{
    size = strlen (s);
    str = new char[size + 1];
    strcpy(str,s);
    
}

bool myString::empty()
{
    return !size;
}

int myString::my_size()
{
    return size;
}

int myString::my_length()
{
    return strlen(str);
}

char* myString::my_str()
{
    return str;
}

char& myString::at(int index)
{
    return str[index];
}

bool myString::expend()
{
    size *= 2;
    char* temp;
    temp = new char[size +1];
    delete str;
    str = temp;
    temp = NULL;
    
    return true;
}


http://www.kler.cn/a/282242.html

相关文章:

  • Halcon HImage 与 Qt QImage 的相互转换(修订版)
  • 【Fargo】23:采集时间转rtp时间
  • Gin 框架中间件详细介绍
  • 为正在运行的 Docker 容器重启策略,以提高服务的可用性
  • ARM(安谋) China处理器
  • 【H3C华三 】VRRP与BFD、Track联动配置案例
  • 【C++ 面试 - 内存管理】每日 3 题(八)
  • 系统中没有安装 git
  • 鸿蒙南向开发:测试框架xdevice核心组件
  • pnpm国内源设置
  • 苹果手机系统修复如何操作,几种iOS系统修复办法分享
  • Oracle(89) 什么是等待事件(Wait Event)?
  • mysql-day03
  • 行为型设计模式-观察者(observer)模式
  • 机器学习/数据分析--通俗语言带你入门随机森林,并用随机森林进行天气分类预测(Accuracy为0.92)
  • Nginx中设置服务器备用(backup)状态的策略与实践
  • 16. 结构体占内存大小是怎么计算的,有哪些原则?
  • OJ-0829
  • Python 中的 `and`, `or`, `not` 运算符:介绍与使用
  • Linux进程间的通信(二)管道通信及其实际应用(主要是实际编程应用,底层涉及不太多,想了解底层参考《UNIX环境高级编程》)
  • C++ QT 单例模式
  • uniapp秋云图表报错json underfind的原因
  • 【C#】【EXCEL】Bumblebee/Components/Analysis/GH_Ex_Ana_CondBetween.cs
  • 《python语言程序设计》2018版第8章第6题统计字符串中的字母个数
  • C#实现文件的上传
  • 华为AR路由使用PPPoE获取IPv6地址上网