目录
1.类的6个默认成员函数
2. 构造函数
2.1 概念
2.2 特性
3.析构函数
3.1 概念
3.2 特性
4. 拷贝构造函数
4.1 概念
4.2 特征
1.类的6个默认成员函数
class Date {}; //空类
2. 构造函数
2.1 概念
class Date
{
public:
void Init(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
d1.Init(2022, 7, 5);
d1.Print();
Date d2;
d2.Init(2022, 7, 6);
d2.Print();
return 0;
}
2.2 特性
class Date
{
public:
// 1.无参构造函数
Date()
{}
// 2.带参构造函数
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
void TestDate()
{
Date d1; // 调用无参构造函数
Date d2(2015, 1, 1); // 调用带参的构造函数
// 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明
// 以下代码的函数:声明了d3函数,该函数无参,返回一个日期类型的对象
// warning C4930: “Date d3(void)”: 未调用原型函数(是否是有意用变量定义的?)
Date d3();
}
class Date
{
private:
// 基本类型(内置类型)
int _year = 1970;
int _month = 1;
int _day = 1;
// 自定义类型
Time _t;
};
class Date
{
public:
//无参的构造函数
Date()
{
_year = 1900;
_month = 1;
_day = 1;
}
//全缺省的构造函数
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
3.析构函数
3.1 概念
3.2 特性
析构函数是特殊的成员函数,其特征如下:
以下为栈的实现
#include<iostream>
using namespace std;
#include<stdlib.h>
#include<assert.h>
typedef int DataType;
struct Stack
{
public:
void Init()
{
_array = (DataType*)malloc(10 * sizeof(DataType));
if (NULL == _array)
{
assert(false);
return;
}
//没上面问题容易给3,数量为0
_capacity = 10;
_size = 0;
}
//入栈
void Push(DataType data)
{
_array[_size] = data;
++_size;
}
//出战
void Pop()
{
if (Empty())
return;
_size--;
}
//获取栈顶元素
DataType Top()
{
assert(!Empty());
return _array[_size - 1];
}
bool Empty()
{
return 0 == _size;
}
int Size()
{
return _size;
}
void Destroy()
{
if (_array)
{
free(_array);
_array = nullptr;
_capacity = 0;
_size = 0;
}
}
private:
//扩容方法
void _CheckCapacity()
{
}
private:
DataType* _array;
size_t _capacity;
size_t _size;
};
int main()
{
Stack s;
s.Init();
s.Push(1);
s.Push(2);
s.Push(3);
s.Push(4);
s.Push(5);
cout << s.Top() << endl;
cout << s.Size() << endl;
s.Pop();
s.Pop();
cout << s.Top() << endl;
cout << s.Size() << endl;
s.Destroy();
return 0;
}
因为我们代码中自己写了初始化 Init 和 Destory,所以在主函数中你要进行栈操作,必须手动加上s.Init();以及s.Destroy(); 要是不加就会崩溃,这样的话你总有失误的时候,此时我们想让栈创建好就有空间,所以对代码需要优化,下面为部分优化代码
~Stack()
{
if (_array)
{
free(_array);
_array = nullptr;
_capacity = 0;
_size = 0;
}
}
void TestStack()
{
Stack s;
s.Push(1);
s.Push(2);
s.Push(3);
s.Push(4);
s.Push(66);
cout << s.Top() << endl;
cout << s.Size() << endl;
s.Pop();
s.Pop();
cout << s.Top() << endl;
cout << s.Size() << endl;
}
int main()
{
TestStack();
return 0;
}
注意:像Date类一样,对象中没有涉及到任何资源管理时,该类的析构函数可以不必给出
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << _year << "/" << _month << "/" << _day << endl;
}
~Date()
{
cout << "~Date():" << this << endl;
}
private:
int _year;
int _month;
int _day;
};
void TestDate()
{
Date d(2022, 11, 22);
}
int main()
{
void TestDate();
return 0;
}
4. 拷贝构造函数
4.1 概念
4.2 特征
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
Date d2(d1);
错误例子如下:如果这样使用,会不断的调用拷贝,这就是传值引发对象的拷贝
Date(const Date& d)
问题:编译器生成的拷贝构造,虽然没有生成但是可以完成拷贝构造的工作,既然编译器已经可以完成了,那拷贝构造函数还需要用户自己写吗?、
答:像日期这种没有涉及到资源管理时, 可写可不写,一般不写,因为编译器可以完成拷贝的工作,如果需要自己再去实现,注意编译器是按照值的方式拷贝的---即:将一个对象中的内容原封不动的拷贝到另一个对象中(浅拷贝)
注意:
// 1. 以值的方式返回时,如果返回的是匿名对象,则编译器不会再用匿名对象
// 拷贝构造临时对象,而是直接将匿名对象返回了
// 匿名对象:没有名字的对象
// 2. 如果参数是以值的方式传递,实参如果也是匿名对象,也会少一次拷贝构造
// 3. 在C++中,参数能使用引用尽量使用引用,如果不想通过形参改变外部的实参,尽量设置为const类型的引用