本文是接续文章类与对象(上)的。
如果一个类中什么成员都没有,则称这个类为空类,但空类中并不是什么都没有,而是存在六个默认成员函数(用户没有显式实现,编译器会生成的成员函数)。即任何类在什么都不写的情况下,编译器会自动生成六个默认成员函数。
构造函数是一个特殊的成员函数,它的函数名与类名相同,当创建类类型对象时,编译器会自动调用这个函数,以保证每个数据成员都有一个合适的初始值,并且在对象的整个生命周期内只调用一次。
class Date
{
public:
//Date() //无参构造函数
//{}
Date(int year = 2023, int month = 8, int day = 17) //全缺省构造函数
{
_year = year;
_month = month;
_day = day;
}
private:
int _year = 1;
int _month = 1;
int _day = 1;
};
内置类型:语言提供的数据类型,如:int、char、double等等。
自定义类型:我们使用class、struct、union等等,自己定义的类型。
编译器生成的默认构造函数在进行初始化时,对内置类型不做处理,而对自定义类型会去调用它(这个自定义类型)的默认构造函数。
class Time
{
public:
Time()
{
_hour = 0;
_minute = 0;
_second = 0;
}
private:
int _hour;
int _minute;
int _second;
};
class Date
{
public:
private:
//内置类型(基本类型)
int _year;
int _month;
int _day;
// 自定义类型
Time _t;
};
int main()
{
Date d;
return 0;
}
析构函数与构造函数的功能相反,析构函数不是完成对对象本身的销毁,因为局部对象销毁工作是由编译器完成的,而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。
typedef int DataType;
class Stack
{
public:
//构造函数
Stack(size_t capacity = 3)
{
_array = (DataType*)malloc(sizeof(DataType) * capacity);
if (NULL == _array)
{
perror("malloc申请空间失败!!!");
return;
}
_capacity = capacity;
_size = 0;
}
void Push(DataType data)
{
_array[_size] = data;
_size++;
}
// 其他方法...
~Stack()
{
if (_array)
{
free(_array);
_array = NULL;
_capacity = 0;
_size = 0;
}
}
private:
DataType* _array;
int _capacity;
int _size;
};
class MyQueue
{
public:
private:
Stack st1;
Stack st2;
};
int main()
{
MyQueue mq;
return 0;
}
在创建对象时,创建一个与已存在对象一某一样的新对象。
只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。
class Date
{
public:
Date(int year = 2023, int month = 8, int day = 17)
{
_year = year;
_month = month;
_day = day;
cout << "Date(int year = 2023, int month = 8, int day = 17)" << endl;
}
Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
cout << "Date(const Date& d):" << &d << endl;
}
~Date()
{
cout << "~Date():" << this << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2023, 8, 19);
Date d2(d1);
return 0;
}
class Date
{
public:
Date(int year = 2023, int month = 8, int day = 17)
{
_year = year;
_month = month;
_day = day;
cout << "Date(int year = 2023, int month = 8, int day = 17)" << endl;
}
Date(const Date d)
{
_year = d._year;
_month = d._month;
_day = d._day;
cout << "Date(const Date& d):" << &d << endl;
}
~Date()
{
cout << "~Date():" << this << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2023, 8, 19);
Date d2(d1);
return 0;
}
int main()
{
Stack st1;
st1.Push(1);
st1.Push(2);
st1.Push(3);
st1.Push(4);
Stack st2(st1);
return 0;
}
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,它具有返回值类型,函数名以及参数列表,其返回值类型和参数列表与普通的函数类似。
形式参数类型:const 类类型&,形式参数使用引用可以提高传参的效率。
返回值类型:类类型&,返回值类型使用引用可以提高返回的效率,有返回值的目的是为了支持连续赋值。
//Date.h
class Date
{
public:
// 全缺省的构造函数
Date(int year = 2023, int month = 8, int day = 20)
{
if (month < 1 || month > 12
|| day < 1 || day > GetMonthDay(year, month))
{
cout << "非法日期" << endl;
}
_year = year;
_month = month;
_day = day;
}
Date& operator=(const Date& d);
private:
int _year;
int _month;
int _day;
};
//Date.cpp
Date& Date::operator=(const Date& d)
{
if (this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
//赋值运算符重载测试代码
int main()
{
Date d3(2023, 8, 21);
Date d4, d5;
d5 = d4 = d3;
return 0;
}
被const修饰的“成员函数”称之为const成员函数,当const修饰类成员函数时,实际修饰的是该成员函数形参列表中隐含的this指针形参,表明在该成员函数中不能对this指向的类的任何成员进行修改。
#include
using namespace std;
class Date
{
public:
Date(int year = 2023, int month = 8, int day = 22)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << "Print()" << endl;
cout << _year << " " << _month << " " << _day << endl;
}
//实际的参数:void Print(const Date* const this)
void Print() const
{
cout << "Print()const" << endl;
cout << _year << " " << _month << " " << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
const Date d2;
d1.Print();
d2.Print();
return 0;
}
本文到这里就结束了,如有错误或者不清楚的地方欢迎评论或者私信
创作不易,如果觉得博主写得不错,请务必点赞、收藏加关注