【C++】类和对象(二)

夜晚中的人海 2024-07-28 08:35:01 阅读 54

在这里插入图片描述

个人主页

在这里插入图片描述

创作不易,感谢大家的关注!

文章目录

⭐一、类的默认成员函数💎二、构造函数⏱️三、析构函数🏝️ 四、拷贝构造函数🎄五、赋值运算符重载🏠六、取地址运算符重载🎉const成员

⭐一、类的默认成员函数

定义:所谓的默认成员函数,就是用户没有显式实现,而编译器会自动生成的成员函数就被称为默认成员函数。

在一个类中,在我们不写的情况下编译器会自动生成以下六个默认成员函数。其中最重要的是前四个,而取地址重载可以作为了解即可。

在这里插入图片描述

💎二、构造函数

定义:构造函数是一个特殊的成员函数,其名字与类名相同,在创建类类型对象时由编译器自动调用,保证每一个对象成员都有初始值,并在对象的生命周期内只调用一次。

特点:

1.函数名与类名相同。

2.没有返回值。

3.对象实例化时系统会自动调用对应的构造函数。

4.构造函数可以重载。

功能:

构造函数不是用来构造对象的,它是来完成对象初始化的。

注意事项:

1.如果类中没有显式定义构造函数,那么C++编译器会自动生成一个无参的默认构造函数,一旦用户定义则编译器将不再生成。

2.无参构造函数、全缺省构造函数和当我们不写构造时编译器默认生成的构造函数,都被称为默认构造函

数。但是这三个函数有且仅有一个存在,不能同时存在。

演示代码:

<code>#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>

using namespace std;

class Date

{

public:

// 1.无参构造函数

Date()

{

_year = 1;

_month = 1;

_day = 1;

}

//2.带参构造函数

Date(int year, int month, int day)

{

_year = year;

_month = month;

_day = day;

}

//3.全缺省构造函数

Date(int year = 1, int month = 1, int day = 1)

{

_year = year;

_month = month;

_day = day;

}

private:

int _year;

int _month;

int _day;

};

⏱️三、析构函数

概念:与构造函数的功能相反,析构函数并不是完成对对象本身的销毁,C++规定对象在销毁时会自动调用析构函数,完成对象中资源的清理释放工作。特点:

1.析构函数名是在类名前加上字符 ~。

2.无参数和无返回值。

3.⼀个类只能有⼀个析构函数。若未显式定义,系统会自动生成默认的析构函数。

4.对象生命周期结束时,编译器会自动调用析构函数。功能:

完成对象中资源的清理释放工作。注意事项:

1.我们不写编译器自动生成的析构函数对内置类型成员不做处理,自定义类型成员会调用他的析构函数。

2.如果类中没有申请资源时,析构函数可以不写,直接使用编译器自动生成的默认析构函数。

(注:在有资源申请时,一定要自己写析构函数,否则会造成资源泄露)

3.一个局部域的多个对象,C++规定后定义的先析构。

代码演示:

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>

using namespace std;

class Time

{

public:

//析构函数

~Time()

{

cout << "~Time()" << endl;

}

private:

int _hour;

int _minute;

int _second;

};

class Date

{

public:

private:

int _year;

int _month;

int _day;

// 自定义类型

Time _t;

};

int main()

{

Date a;

return 0;

}

🏝️ 四、拷贝构造函数

概念:拷贝构造函数是通过一个对象来初始化另一个对象,也是一个特殊的构造函数。特点:

1.拷贝构造函数是构造函数的⼀个重载。

2.拷贝构造函数的参数只有⼀个且必须是类类型对象的引用,使用传值方式是编译器会产生报错,因为在语法逻辑上会引发无穷递归。

3.C++规定自定义类型对象在进行拷贝行为时必须调用拷贝构造。注意事项:

若未显式定义拷贝构造时,编译器会自动生成拷贝构造函数。而自动生成的拷贝构造对内置类型成员变量会完成值拷贝或浅拷贝(⼀个字节⼀个字节的拷贝),在对自定义类型成员变量时会调用它本身的拷贝构造。

代码演示:

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>

using namespace std;

class Date

{

public:

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(2024, 7, 20);

//用已存在的对象d1来初始化对象d2

Date d2(d1);

d1.Print();

d2.Print();

return 0;

}

🎄五、赋值运算符重载

定义:C++为了增强代码的可读性引入了运算符重载,允许我们通过运算符重载的形式来指定新的含义。

特点:

1.运算符重载是具有特殊名字的函数,它的名字是由operator和后面要定义的运算符共同构成,具有其返回类型和参数列表以及函数体。

2.运算符重载以后,其优先级和结合性与对应的内置类型运算符保持⼀致。

3.如果⼀个重载运算符函数是成员函数,则它的第⼀个运算对象默认传给隐式的this指针,因此运算符重载作为成员函数时,参数比运算符对象少⼀个。

注意事项:

1.不能通过连接语法中没有的符号来创建新的操作符:比如operator@。

2.重载操作符至少有⼀个类类型参数,不能通过运算符重载改变内置类型对象的含义。

3.sizeof 、:: 、.* 、?: 、. 这5个运算符不能重载。

4.重载++运算符时,有前置++和后置++,因此.C++规定,后置++重载时,增加⼀个int形参,跟前置++构成函数重载,方便区分。

5.重载<<和>>时,需要重载为全局函数,因为重载为成员函数时,this指针默认抢占了第⼀个形参位置,而第一个形参的位置为左侧运算符对象。而重载为全局函数时就可以把ostream/istream放到第⼀个形参位置。

🏠六、取地址运算符重载

取地址运算符重载分为普通取地址运算符重载和const取地址运算符重载,⼀般这两个函数由编译器自动生成的就足够我们使用了,不需要额外去显式实现。

🎉const成员

定义:将const修饰的成员函数就称为const成员函数,const修饰成员函数放到成员函数参数列表的后面。

功能:const实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。

下面有这么几个问题:

1.const成员能够调用非const成员的函数吗?

2.非const成员可以调用const成员函数吗?

3.const成员函数内可以调用其他的非const成员函数吗?

4.非cosnt成员函数内可以调用其他的cosnt成员函数吗?

我们先来揭晓答案:

1.不可以 2.可以 3.不可以 4.可以

下面对上述问题进行阐释:

1.非const成员函数,即成员函数的this指针没有被const所修饰,当我们传入一个const修饰的对象时,被一个非const修饰的成员函数所接受,属于权限放大,因此函数调用失败。

2.const成员函数,即成员函数的this指针被const所修饰,当我们传入一个非const修饰的对象时,被一个const修饰的成员函数所接受,属于权限缩小,函数调用成功。

3…在一个被const所修饰的成员函数中调用其他没有被const所修饰的成员函数,属于权限的放大,因此函数调用失败。

4.在一个没有被const所修饰的成员函数中调用其他被const所修饰的成员函数,属于权限缩小,函数调用成功。

总结:权限可以被放大,但不能被缩小,否则就会出现报错。



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。