在前面简单的介绍了OOP,什么是类,在类中的this指针。接下来就深入理解类和对象。
接下来就依次介绍默认成员函数
构造函数类似于初始化函数,在写Stack时候,首先需要初始化Stack。
构造函数并不是开辟空间创建对象,而是初始化
class Date { public: //构造函数 Date() //无参构造函数 { } Date(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 d0;//调用无参数构造 初始化的值是随机值 Date d1(2024, 7.1, 8);//调用带参构造 d1.Print(); return 0; }
注意:在调用无参构造函数,初始化时候是随机值。
class Date { public: //Date(int year, int month, int day) //{ // _year = year; // _month = month; // _day = day; //} private: int _year; int _month; int _day; }; int main() { Date d0; Date d1; d1.Print(); return 0; }
注意:在 (C++11) 中,针对内置类型不初始化打了补丁,成员变量在声明的时候可以给默认值
class Date { private: int _year = 1; int _month = 1; int _day = 1; };
无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。
注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为 是默认构造函数。
//无参构造函数 Date(int year, int month, int day) { _year = year; _month = month; _day = day; } //全缺省构造函数 Date(int year = 1, int month = 1, int day = 1) { _year = year; _month = month; _day = day; }
//在这里面以以 Stack 为例 class Stack { ~Stack() { free(_a); _a = nullptr; } private: int* _a; int _capacity; int _size; };
class Date { public: Date(int year = 1, int month = 1, int day = 1) { _year = year; _month = month; _day = day; } // DateP(const Date d); 错误示范 Date(const Date& d) { _year = d._year; _month = d._month; _day = d._day; } private: int _year; int _month; int _day; }; int main() { Date d1(2024,7,9); Date d2(d1); return 0; }
注意 : 如果拷贝构造函数不加引用,会发生无穷递归. 函数在传值调用会调用拷贝构造函数,如其函数不加入引用(即传值调用),就会发生无限递归.
浅拷贝:浅拷贝是指复制对象时只复制其基本数据类型成员和指针成员,而不复制指针所指向的内存内容
深拷贝:深拷贝则是在复制对象时,不仅复制基本数据类型成员和指针成员,还会为指针所指向的内存内容分配新的内存空间,并将原有内容复制过去。
operator
后跟要重载的运算符符号来命名。this
指针)。非成员函数形式的运算符重载则适用于不涉及类对象或需要对称操作的场合。+
)应该执行加法操作,而不是其他操作。注意:
const
引用,以避免在赋值后对当前对象进行不必要的修改。class Date { public : Date(int year = 1900, int month = 1, int day = 1) { _year = year; _month = month; _day = day; } Date (const Date& d) { _year = d._year; _month = d._month; _day = d._day; } //赋值运算符重载 Date& operator=(const Date& d)//返回this,用来连续赋值。 { if(this != &d) { _year = d._year; _month = d._month; _day = d._day; } return *this; } private: int _year ; int _month ; int _day ; };
赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现 一个全局的赋值运算符重载,就 和编译器在类中生成的默认赋值运算符重载冲突了,故赋值 运算符重载只能是类的成员函数。
在下面的例子中:
前置:
后置:
// 前置++ Date& Date::operator++() { return *this += 1; } // 后置++ Date Date::operator++(int) { Date tmp; tmp += 1; return *this; }
在这里和前置++ 后置++ 思想一致。
// 后置-- Date Date::operator--(int) { Date tmp; tmp -= 1; return *this; } // 前置-- Date& Date:: operator--() { return *this -= 1; }