目录
默认成员函数
1.构造函数
1.1构造函数的概念
1.2自己写的构造函数以及怎样调用
1.2.1日期的实现
1.2.2栈的实现
1.3编译器生成的默认构造函数
1.3.1日期的实现
1.3.1栈的实现
1.3.3队列(两个栈实现一个队列)的实现
2.析构函数
2.1析构函数的概念
2.2自己写的析构函数
2.2.1日期的实现
2.2.2栈的实现
2.3.编译器生成的默认析构函数
2.4 Stack类使用默认析构函数的危害
3.拷贝构造函数
3.1拷贝构造函数的概念
3.2浅拷贝与深拷贝
3.3拷贝构造函数的实现
3.3.1Stack对象的拷贝构造
4.赋值运算符重载
4.1运算符重载
4.2赋值运算符重载
默认成员函数
在c++类中,有这样6个成员函数,你不写编译器会自动帮我们生成,这样的函数就叫做默认成员函数。
1.构造函数
1.1构造函数的概念
类似于函数的初始化,没有返回值,函数名很类名相同,生成对象时自动调用。注意:不是创建类,而是对类进行初始化
1:你不写编译器会自动帮我们生成并且调用编译器生成的构造函数,内置类型不做处理,自定义类型会去调用它的构造函数。
2:你写了构造函数编译器会调用你写的构造函数。
1.2自己写的构造函数以及怎样调用
自己写的构造函数分为全缺省构造函数和半缺省构造函数,这边写哪个都可以,但是需要注意的是它们两个不能同时存在
1.2.1日期的实现
class Date
{
public:
//构造函数
//1.全缺省构造函数
Date(int year = 2023 ,int month = 10, int day = 7)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
void Test1()
{
//自动调用全缺省构造函数
Date d1;
d1.Print();//d1的日期为2023-10-7
return;
}
1.2.2栈的实现
/// //
class Stack
{
public:
//1.全缺省构造函数
Stack(int capacity = 4)
{
int* _a = (int*)malloc(sizeof(int) * 4);
//如果申请不成功
if (_a == nullptr)
{
perror("malloc申请空间失败!!!:");
exit(-1);
}
_top = 0;
_capacity = capacity;
}
private:
int* _a;
int _top;
int _capacity;
};
void Test2()
{
//在创建st1对象时自动调用构造函数,自动初始化。
Stack st1;
}
1.3编译器生成的默认构造函数
1.3.1日期的实现
class Date
{
public:
//构造函数自动生成
//打印函数
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
void Test1()
{
Date d1;
d1.Print();//d1的日期为随机值
return;
}
1.3.1栈的实现
class Stack
{
public:
//自动生成构造函数
private:
int* _a;
int _top;
int _capacity;
};
void Test2()
{
//在创建st1对象时自动调用构造函数,自动初始化。
Stack st1;//_a指针、_top、_capacaty全为随机值
}
1.3.3队列(两个栈实现一个队列)的实现
class MyQueue
{
public:
//Stack类型的会去调用自己的构造函数
Stack pushst;
Stack popst;
//内置类型不做处理,默认为缺省值100
int _size = 100;
};
void Test3()
{ //自定义类型q1.pushst和q1.popst会去调用他们自己的构造函数
//内置类型q1._size不做处理,为缺省值100
MyQueue q1;
return;
}
2.析构函数
2.1析构函数的概念
类似于函数的销毁,没有返回值,函数名为 ~ + 类名,生成对象时自动调用。
1:你不写编译器会自动帮我们生成并且调用编译器生成的构造函数,内置类型不做处理,自定义类型会去调用它的构造函数。
2:你写了析构函数编译器会调用你写的析构函数。
2.2自己写的析构函数
出了作用域自动调用析构函数。
2.2.1日期的实现
//2.析构函数(日期)
~Date()
{
_year = 0;
_month = 0;
_day = 0;
}
2.2.2栈的实现
//2.析构函数
~Stack()
{
free(_a);
_a = nullptr;
_top = 0;
_capacity = 0;
}
2.3.编译器生成的默认析构函数
内置类型:销毁时不需要进行资源清理,最后系统直接回收即可
自定义类型:有资源申请时一定要自己写析构函数,否则会造成内存泄漏
日期:Date的对象可以直接调用系统默认的析构函数。
栈:一定要调用自己的析构函数,用系统调用的析构函数会出现内存泄漏等问题!
队列(两个栈实现一个队列):内置类型不需要进行资源清理,Stack类的对象调用它的析构函数即可。
2.4 Stack类使用默认析构函数的危害
如果有malloc、realloc生成的这类空间,默认的析构函数是不会对这部分空间进行资源回收的,所以就会有很多没有用的空间还存在着,俗称占着茅坑不拉屎!,严重影响系统的资源管理。造成效率的损失!!!
3.拷贝构造函数
3.1拷贝构造函数的概念
本质上来讲是构造函数的重载函数,没有返回值,函数名等于类名,函数参数等于类名的引用。
1:你不写编译器会自动帮我们生成并且调用编译器生成的拷贝构造函数,内置类型完成浅拷贝,自定义类型会去调用它的拷贝构造函数。
2:你写了拷贝构造函数编译器会调用你写的拷贝构造函数。
3.2浅拷贝与深拷贝
int main()
{
Stack s1;
//将s1拷贝到s2
Stack s2(s1);
return 0;
}
红色为原来就有的对象st1,黑色为拷贝st1的st2.
浅拷贝:
int *s2._a = s1._a;
s2._top = s1._top
s2._capacity = s1._capacity;
深拷贝:
int *s2._a = (int *)malloc(sizeof(int )*n);
s2._top = s1._top
s2._capacity = s1._capacity;
使用默认的拷贝构造函数会出现的问题:
使用浅拷贝:出了作用域,调用析构函数时,同一块空间将被释放两次,出现内存泄漏的问题!
3.3拷贝构造函数的实现
日期:浅拷贝,直接用默认的就行
栈:深拷贝!!!
队列:用默认的(内置类型进行浅拷贝,自定义类型调用它的拷贝构造)文章来源:https://www.toymoban.com/news/detail-734130.html
3.3.1Stack对象的拷贝构造
//3.拷贝构造函数
Stack(const Stack& sdd)
{
//拷贝的st2指向另外一块跟st1相同大小的空间
_a = (int*)malloc(sizeof(int) * sdd._capacity);
_top = sdd._top;
_capacity = sdd._capacity;
}
4.赋值运算符重载
4.1运算符重载
C++ 为了增强代码的可读性引入了运算符重载 , 运算符重载是具有特殊函数名的函数 ,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。函数名字为:关键字 operator 后面接需要重载的运算符符号 。函数原型: 返回值类型 operator 操作符 ( 参数列表 )注意:不能通过连接其他符号来创建新的操作符:比如 operator@重载操作符必须有一个类类型参数用于内置类型的运算符,其含义不能改变,例如:内置的整型 + ,不 能改变其含义作为类成员函数重载时,其形参看起来比操作数数目少 1 ,因为成员函数的第一个参数为隐藏的 this.* :: sizeof ?: . 注意以上 5 个运算符不能重载。这个经常在笔试选择题中出现。
具体实现可以看我这一篇博客文章来源地址https://www.toymoban.com/news/detail-734130.html
4.2赋值运算符重载
1. 赋值运算符重载格式参数类型 : const Dyte& ,传递引用可以提高传参效率返回值类型 :Dyte & ,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值检测是否自己给自己赋值返回 *this :要复合连续赋值的含义
//赋值运算符重载
bool Date::operator==(const Date& dd)
{
return _year == dd._year && _month == dd._month && _day == dd._day;
到了这里,关于c++6大默认成员函数(类与对象中)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!