C++类、构造函数、析构函数

class类:

        相当于C语言结构体,不过里面可以包含各种函数,有公有区域public和私有区域private,只有在类中的成员函数或成员变量可以访问私有区域。类中自带两个初始化函数:构造函数和析构函数

        在Date类中的函数,为了能让主函数识别多个Date类型的变量,类中的函数一般都自带 Date* this 的一个形参,来识别是那个Date类型变量,当然函数中也可以调用this

        private中的成员变量都是声明,并不没有开空间,且独立存储,当类对象实例化后

Data d1; 才会开空间

class Date  //类
{
public://公有 声明在public后面的成员所有人都是可以使用
    //void Init(Date* this,编译器增加的 存在栈中 int year,int month,int day)
    void Init(int year,int month,int day)//成员函数是一样的,放到公共区域(代码段)
    {
        _year=year;
        _month=month;
        this->_day=day;//可以调用this
        cout << this << endl; //可以在函数里面调用this 输出地址
    }
    void func1()
    {
        cout << "func()" << endl;
    }
//private://私有 只有类内的成员函数才可以访问
    int _year;  //声明 没开空间
    int _month; //成员变量是不一样的要独立存储
    int _day;
};

class A
{};//为空的类 被实例化时会有1byte的占位大小
int test1()
{
    Date d1;    //类对象实例化 -- 开空间
    //d1.Init(&d1,2023,2,2); 编译器会给d1地址给函数Init
    d1.Init(2023,2,2);
    cout << d1._year << endl;
    cout << sizeof(d1) << endl;//只有成员变量占位 成员函数在公共区域
    A A1;
    cout << sizeof(A1) << endl;//为空的类 被实例化时会有1byte的占位大小

    Date* ptr= nullptr;
    ptr->func1();    //正常运行
    (*ptr).func1();  //正常运行
    //ptr->Init(2023,2,2)   //运行崩溃  ptr是空地址 会传给this   this->_year会崩溃 this是空指针

    return 0;
}

构造函数和析构函数

//构造函数——对象实例化时编译器自动调用,函数名与类名相同,无返回值所以不用加类型,可重载 //析构函数——对象生命周期结束时自动调用,函数名是在类名前加上~,一个类只能有一个析构函数,不能重载
class Stack
{
public:
    Stack()
    {
        cout << "Stack()" << endl;

        _a= nullptr;
        _size=0;
        _capacity=0;
    }
    Stack(int n)//可以有多个构造函数
    {
        cout << "Stack(int n)" << endl;

        _a=(int*)malloc(sizeof(int)*n);//开辟空间
        if(_a== nullptr)
        {
            perror("malloc error");
            exit(-1);
        }
        _capacity=n;
        _size=0;
    }
    ~Stack()
    {
        cout << "~Stack()" << endl;
        if(_a)
        {
            free(_a);
            _a = nullptr;
            _size=_capacity=0;
        }

    }
private:
    int* _a;
    int _size;
    int _capacity;
};
int test2()//构造函数和析构函数
{
    Stack st1;
    Stack st2(4);


    return 0;
}

//默认生成构造和析构函数、拷贝构造

如果写了任意一个构造函数,编译器就不会生成默认的构造函数

不处理内置类型,处理自定义类型

tip:内置类型:int/char/double.... 自定义类型:class/struct.....

operator 重载复用

变量的构造、析构和栈一样,先进后析构,后进的先析构

class Date2
{
public://如果写了任意一个构造函数,编译器就不会生成默认的构造函数
    Date2(int year,int month,int day)
    {
        cout << "Date2()" << endl;

        _year=year;
        _month=month;
        _day=day;
    }
    //拷贝构造
    Date2(const Date2& d)//const:防止修改引用的参数中的数据  传引用传参 如果传形参 会无限递归
    {
        cout << "Date2(const Date2& d)" << endl;

        _year=d._year;//防止写反⬆
        _month=d._month;
        _day=d._day;
    }

    bool operator==(const Date2& d)//两个参数 一个this 一个d
    {
        return _year==d._year
               && _month==d._month
               && _day==d._day;
    }

    bool operator<(const Date2& d)
    {
        return
        _year<d._year||
        _year==d._year && _month<d._month||
        _year==d._year && _month==d._month&&_day<d._day;
    }
    bool operator<=(const Date2& d)//复用
    {
        return *this == d || *this < d;
    }
    bool operator>(const Date2& d)
    {
        return !(*this <=d);
    }
    bool operator>=(const Date2& d)
    {
        return *this > d || *this == d;
    }
    bool operator!=(const Date2& d)
    {
        return !(*this == d);
    }

    Date2& operator=(const Date2& d)//返回引用参数 支持连续赋值 d1=d2=d3
    {
        if(this==&d) return *this;//d1=d1自己给自己赋值直接返回
        _year=d._year;
        _month=d._month;
        _day=d._day;
        return *this;
    }
    void Print()
    {
        cout << _year << " ";
        cout << _month << " ";
        cout << _day << endl;
    }
private:
    int _year;
    int _month;
    int _day;
};
class MyQueue
{
public:
    //默认生成的构造函数对内置类型不处理,只处理自定义类型
    void Print()
    {
        _day=10;//假如这个是构造函数内的
        cout << _year << " ";
        cout << _month << " ";
        cout << _day << endl;
    }

    Stack _pushST;
    Stack _popST;
    int size;//clion编译器初始化会变成 1
private:
    //声明位置给缺省值,如果没自定义构造函数,则内置类型用缺省值
    int _year=2023;
    int _month=2;
    int _day=3;
};
//tip:内置类型:int/char/double.... 自定义类型:class/struct.....
//默认生成的构造函数、析构函数,不处理内置类型,处理自定义类型

int test3()//默认生成构造和析构函数、拷贝构造
{   //tip:如果没写上面两个构造函数
    //Date2 d1(); (年月日是随机值) 可以编译,用编译器自动生成的 无参的构造函数,
    Date2 d1(2023,2,3);
    //拷贝构造
    Date2 d2(d1); //两种拷贝
    Date2 d3=d1;

    //默认构造、析构函数测试
    MyQueue q;
    q.Print();


    return 0;
}

//深 拷贝函数

全缺省构造和无参构造冲突,半缺省不会

如果不开辟空间再拷贝过去,st1._array和st2._array会共用一个地址 崩溃

typedef int DateType;
class Stack2
{
public:
//    Stack2()
//    {
//        cout << "Stack2()" << endl;
//
//        _array= nullptr;
//        _size=0;
//        _capacity=0;
//    }
    Stack2(int n=10)//tip:全缺省构造和无参构造冲突,半缺省不会
    {
        cout << "Stack2(int n=10)" << endl;

        _array=(DateType *)malloc(sizeof(DateType)*n);
        if(_array== nullptr)
        {
            perror("malloc error");
            exit(-1);
        }
        _capacity=n;
        _size=0;
    }
    Stack2(const Stack2& st)//深拷贝 如果不开辟空间再拷贝过去,st1._array和st2._array会共用一个地址 崩溃
    {
        cout << "Stack2(const Stack2& st)" << endl;

        _array=(DateType*)malloc(sizeof(DateType)*st._size);
        if(_array== nullptr)
        {
            perror("malloc error");
            exit(-1);
        }
        _size=st._size;
        _capacity=st._capacity;
        memcpy(_array,st._array,st._capacity);
    }

    ~Stack2()
    {
        cout << "~Stack2()" << endl;
        if(_array)
        {
            free(_array);
            _array = nullptr;
            _size=_capacity=0;
        }

    }
private:
    DateType* _array;
    int _size;
    int _capacity;
};
int test4()//深 拷贝函数
{
    Stack2 st;//tip:无参(不加括号)使用的是全缺省构造,编译器分不出来全缺省和无参构造,会冲突
    Stack2 st1(20);
    Stack2 st2(st1);//这种情况如果不写拷贝构造,Stack2中的数组_array共用一个地址,当st2析构后,st1的就是野指针,会崩溃
    //和栈一样 先进后析构,后进的先析构
    return  0;
}

//构造和析构的先后顺序

全局变量先构造,局部变量再按顺序构造(不分静态),然后按照动态后入先析构,析构完动态后再静态,后入先析构

class AA
{
public:
    AA()
    {
        cout << "AA" << endl;
    }
    ~AA()
    {
        cout << "~AA" << endl;
    }
};
class BB {
public:
    BB() {
        cout << "BB" << endl;
    }

    ~BB() {
        cout << "~BB" << endl;
    }
};
class CC
{
public:
    CC()
    {
        cout << "CC" << endl;
    }
    ~CC()
    {
        cout << "~CC" << endl;
    }
};
class DD
{
public:
    DD()
    {
        cout << "DD" << endl;
    }
    ~DD()
    {
        cout << "~DD" << endl;
    }

};
// CC c;
int test6()//构造和析构的先后顺序 全局先构造 局部再按顺序构造(不分静态) 然后按照动态后入先析构 析构完动态后再静态,后入先析构
{
    //入栈顺序为 C A B D  出栈顺序为 B A D C
        AA a;
        BB b;//等B A 析构完后再析构D C 全局最后析构
        static DD d;
        return 0;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值