交通设施东莞网站建设广州最新今天的消息
web/
2025/9/26 11:53:22/
文章来源:
交通设施东莞网站建设,广州最新今天的消息,wordpress如何搬站,网站搜索引擎优化的方法各位CSDN的uu们好呀#xff0c;好久没有更新小雅兰的C专栏啦#xff0c;话不多说#xff0c;让我们进入类和对象的世界吧#xff01;#xff01;#xff01; 类的6个默认成员函数
构造函数
析构函数
拷贝构造函数 类的6个默认成员函数
如果一个类中什么成员都没有好久没有更新小雅兰的C专栏啦话不多说让我们进入类和对象的世界吧 类的6个默认成员函数
构造函数
析构函数
拷贝构造函数 类的6个默认成员函数
如果一个类中什么成员都没有简称为空类。
空类中真的什么都没有吗并不是任何类在什么都不写时编译器会自动生成以下6个默认成员 函数。
默认成员函数用户没有显式实现编译器会生成的成员函数称为默认成员函数。
class Date {};构造函数
概念 对于以下Date类 #includeiostream
using namespace std;
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(2023, 8, 9);d1.Print();Date d2;d2.Init(2023, 8, 10);d2.Print();return 0;
}对于Date类可以通过 Init 公有方法给对象设置日期但如果每次创建对象时都调用该方法设置信息未免有点麻烦那能否在对象创建时就将信息设置进去呢 构造函数是一个特殊的成员函数名字与类名相同,创建类类型对象时由编译器自动调用以保证每个数据成员都有 一个合适的初始值并且在对象整个生命周期内只调用一次。 特性 构造函数是特殊的成员函数需要注意的是构造函数虽然名称叫构造但是构造函数的主要任务并不是开空间创建对象而是初始化对象。 也就是说构造函数类比于Init函数 其特征如下 函数名与类名相同。 无返回值不需要写void。 对象实例化时编译器自动调用对应的构造函数。 构造函数可以重载本质就是写多个构造函数提供多种初始化方式。 class Date
{
public://无参构造函数Date(){cout Date() endl;_year 1;_month 1;_day 1;}//带参构造函数Date(int year, int month, int day){cout Date(int year, int month, int day) endl;_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.Print();// 调用带参的构造函数Date d2(2023, 8, 9);d2.Print();// 注意如果通过无参构造函数创建对象时对象后面不用跟括号否则就成了函数声明// 以下代码的函数声明了d3函数该函数无参返回一个日期类型的对象// warning C4930: “Date d3(void)”: 未调用原型函数(是否是有意用变量定义的?)Date d3();d3.Print();return 0;
} //无参构造函数 Date() { cout Date() endl; _year 1; _month 1; _day 1; } //带参构造函数 Date(int year, int month, int day) { cout Date(int year, int month, int day) endl; _year year; _month month; _day day; } 上述两个函数其实可以合并一下写成全缺省参数的形式。 //带参构造函数
Date(int year 1, int month 1, int day 1)
{cout Date(int year, int month, int day) endl;_year year;_month month;_day day;
} 这样的写法也更灵活了可以传一个参数也可以传两个参数也可以传三个参数也可以不传参数。 再看下面这个实例 class Stack
{
public:Stack(size_t n 4){if (n 0){a nullptr;top capacity 0;}else{a (int*)malloc(sizeof(int) * n);if(a nullptr){perror(realloc fail);exit(-1);}top 0;capacity n;}}void Push(int x){if (top capacity){size_t newcapacity capacity 0 ? 4 : capacity * 2;int* tmp (int*)realloc(a, sizeof(int) * newcapacity);if (tmp nullptr){perror(realloc fail);exit(-1);}if (tmp a){cout capacity 原地扩容 endl;}else{cout capacity 异地扩容 endl;}a tmp;capacity newcapacity;}a[top] x;}int Top(){return a[top - 1];}void Pop(){assert(top 0);--top;}void Destroy(){free(a);a nullptr;top capacity 0;}bool Empty(){return top 0;}
private:// 成员变量int* a;int top;int capacity;
};int main()
{Stack st1;st1.Push(1);st1.Push(2);st1.Push(3);st1.Push(4);while (!st1.Empty()){cout st1.Top() ;st1.Pop();}cout endl;st1.Destroy();//Stack st2(1000);Stack st2;for (size_t i 0; i 1000; i){st2.Push(i);}while (!st2.Empty()){cout st2.Top() ;st2.Pop();}cout endl;st2.Destroy();return 0;
} 构造函数是默认成员函数不写编译器会自动生成。 编译生成的默认构造的特点 我们不写才会生成我们写了就不会生成了。内置类型的成员不会处理C11声明支持给缺省值。自定义类型的成员才会处理会去调用这个成员的默认构造函数。 如果类中没有显式定义构造函数则C编译器会自动生成一个无参的默认构造函数一旦 用户显式定义编译器将不再生成。 class Date
{
public:如果用户显式定义了构造函数编译器将不再生成//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类中构造函数屏蔽后代码可以通过编译因为编译器生成了一个无参的默认构造函数// 将Date类中构造函数放开代码编译失败因为一旦显式定义任何构造函数编译器将不再生成// 无参构造函数放开后报错error C2512: “Date”: 没有合适的默认构造函数可用Date d1;d1.Print();return 0;
} 所以默认生成的构造函数一般没什么价值但是在有一些场景下非常有价值之前小雅兰写过一个题目就是两个栈实现一个队列既可以写构造函数也可以不写。 // 两个栈实现一个队列
class MyQueue
{
private:Stack _pushst;Stack _popst;
}; 总结一般情况都需要我们自己写构造函数决定初始化方式 成员变量全是自定义类型可以考虑不写构造函数 关于编译器生成的默认成员函数很多人会有疑惑不实现构造函数的情况下编译器会 生成默认的构造函数。但是看起来默认构造函数又没什么用d对象调用了编译器生成的默 认构造函数但是d对象_year/_month/_day依旧是随机值。也就说在这里编译器生成的默认构造函数并没有什么用 解答C把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类 型如int/char...自定义类型就是我们使用class/struct/union等自己定义的类型看看 下面的程序就会发现编译器生成默认的构造函数会对自定类型成员_t调用的它的默认构造函数。 int*和Date*指针都是内置类型 class Time
{
public:Time(){cout Time() endl;_hour 0;_minute 0;_second 0;}private:int _hour;int _minute;int _second;
};class Date
{
private:// 基本类型(内置类型)int _year;int _month;int _day;// 自定义类型Time _t;
};int main()
{Date d;return 0;
} 注意C11 中针对内置类型成员不初始化的缺陷又打了补丁即内置类型成员变量在 类中声明时可以给默认值。 class Time
{
public:Time(){cout Time() endl;_hour 0;_minute 0;_second 0;}
private:int _hour;int _minute;int _second;
};class Date
{
private:// 基本类型(内置类型)int _year 1970;int _month 1;int _day 1;// 自定义类型Time _t;
};int main()
{Date d;return 0;
}无参的构造函数和全缺省的构造函数都称为默认构造函数并且默认构造函数只能有一个。 注意无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数都可以认为 是默认构造函数。 不传参就可以调用的构造就是默认构造 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;
};// 以下测试函数能通过编译吗
void Test()
{Date d1;
}
int main()
{Test();return 0;
} 上述代码是无法通过编译的。 如果是把无参构造函数屏蔽掉或者是把全缺省构造函数屏蔽掉就可以通过编译了 析构函数
概念
通过前面构造函数的学习我们知道一个对象是怎么来的那一个对象又是怎么没呢的
析构函数与构造函数功能相反析构函数不是完成对对象本身的销毁局部对象销毁工作是由 编译器完成的。而对象在销毁时会自动调用析构函数完成对象中资源的清理工作。
也就是说析构函数类比于Destroy函数
特性 析构函数是特殊的成员函数其特征如下 析构函数名是在类名前加上字符 ~。 无参数无返回值类型。 一个类只能有一个析构函数。若未显式定义系统会自动生成默认的析构函数。注意析构 函数不能重载。对象生命周期结束时C编译系统系统自动调用析构函数。 默认的析构函数跟默认构造函数类似内置类型成员不会处理自定义类型成员会调用这个成员的析构函数。 class Date
{
public:Date(int year 1, int month 1, int day 1){cout Date(int year 1, int month 1, int day 1) endl;_year year;_month month;_day day;}void Print(){cout _year / _month / _day endl;}~Date(){cout ~Date() endl;}private:int _year 1; // 声明给的缺省值int _month 1;int _day 1;
};class Stack
{
public:Stack(size_t n 4){cout Stack(size_t n 4) endl;if (n 0){a nullptr;top capacity 0;}else{a (int*)malloc(sizeof(int) * n);if (a nullptr){perror(realloc fail);exit(-1);}top 0;capacity n;}}~Stack(){cout ~Stack() endl;free(a);a nullptr;top capacity 0;}void Push(int x){if (top capacity){size_t newcapacity capacity 0 ? 4 : capacity * 2;int* tmp (int*)realloc(a, sizeof(int) * newcapacity);if (tmp nullptr){perror(realloc fail);exit(-1);}if (tmp a){cout capacity 原地扩容 endl;}else{cout capacity 异地扩容 endl;}a tmp;capacity newcapacity;}a[top] x;}int Top(){return a[top - 1];}void Pop(){assert(top 0);--top;}void Destroy(){free(a);a nullptr;top capacity 0;}bool Empty(){return top 0;}
private:// 成员变量int* a;int top;int capacity;
};// 两个栈实现一个队列
class MyQueue
{
private:Stack _pushst;Stack _popst;
};
int main()
{Date d1;Date d2;Stack st1;Stack st2;return 0;
} 其实日期类不需要写析构函数 像栈这样的数据结构就需要写析构函数 关于编译器自动生成的析构函数是否会完成一些事情呢下面的程序我们会看到编译器 生成的默认析构函数对自定类型成员调用它的析构函数。 如果类中没有申请资源时析构函数可以不写直接使用编译器生成的默认析构函数比如 Date类有资源申请时一定要写否则会造成资源泄漏比如Stack类。 class Time
{
public:~Time(){cout ~Time() endl;}
private:int _hour;int _minute;int _second;
};class Date
{
private:// 基本类型(内置类型)int _year 1970;int _month 1;int _day 1;// 自定义类型Time _t;
};int main()
{Date d;return 0;
}// 程序运行结束后输出~Time()
// 在main函数中根本没有直接创建Time类的对象为什么最后会调用Time类的析构函数
// 因为main方法中创建了Date对象d而d中包含4个成员变量其中_year, _month, _day三个是
// 内置类型成员销毁时不需要资源清理最后系统直接将其内存回收即可而_t是Time类对象所以在
// d销毁时要将其内部包含的Time类的_t对象销毁所以要调用Time类的析构函数。但是main函数
// 中不能直接调用Time类的析构函数实际要释放的是Date类对象所以编译器会调用Date类的析构函
// 数而Date没有显式提供则编译器会给Date类生成一个默认的析构函数目的是在其内部调用Time
// 类的析构函数即当Date对象销毁时要保证其内部每个自定义对象都可以正确销毁
// main函数中并没有直接调用Time类析构函数而是显式调用编译器为Date类生成的默认析构函数
// 注意创建哪个类的对象则调用该类的析构函数销毁那个类的对象则调用该类的析构函数 拷贝构造函数
概念
在现实生活中可能存在一个与你一样的自己我们称其为双胞胎。 那在创建对象时可否创建一个与已存在对象一模一样的新对象呢
拷贝构造函数只有单个形参该形参是对本类类型对象的引用(一般常用const修饰)在用已存 在的类类型对象创建新对象时由编译器自动调用。
特征 拷贝构造函数也是特殊的成员函数其特征如下 拷贝构造函数是构造函数的一个重载形式。拷贝构造函数的参数只有一个且必须是类类型对象同类型的对象的引用使用传值方式编译器直接报错 因为会引发无穷递归调用。 class Date
{
public:Date(int year 1900, int month 1, int day 1){_year year;_month month;_day day;}// Date(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;Date d2(d1);return 0;
} class Date
{
public:Date(int year 1, int month 1, int day 1){_year year;_month month;_day day;}Date(Date d){cout Date(Date d) endl;_year d._year;_month d._month;_day d._day;}void Print(){cout _year / _month / _day endl;}private:// 内置类型int _year;int _month;int _day;
};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;}Stack(Stack s){cout Stack(Stack s) endl;// 深拷贝_array (DataType*)malloc(sizeof(DataType) * s._capacity);if (NULL _array){perror(malloc申请空间失败!!!);return;}memcpy(_array, s._array, sizeof(DataType) * s._size);_size s._size;_capacity s._capacity;}void Push(DataType data){_array[_size] data;_size;}~Stack(){cout ~Stack() endl;free(_array);_array nullptr;_size _capacity 0;}
private:// 内置类型DataType* _array;int _capacity;int _size;
};void func1(Date d)
{d.Print();
}
// 期望呢s要插入一些数据s的改变不影响s1
void func2(Stack s)
{s.Push(1);s.Push(2);
}int main()
{Date d1(2023, 7, 21);func1(d1);Stack s1;func2(s1);Stack s2(s1);// 以下两个写法是等价的都是拷贝构造Date d2(d1);Date d3 d1;return 0;
} 若未显式定义编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按 字节序完成拷贝这种拷贝叫做浅拷贝或者值拷贝。 class Time
{
public:Time(){_hour 1;_minute 1;_second 1;}Time(const Time t){_hour t._hour;_minute t._minute;_second t._second;cout Time::Time(const Time) endl;}
private:int _hour;int _minute;int _second;
};class Date
{
private:// 基本类型(内置类型)int _year 1970;int _month 1;int _day 1;// 自定义类型Time _t;
};int main()
{Date d1;// 用已经存在的d1拷贝构造d2此处会调用Date类的拷贝构造函数// 但Date类并没有显式定义拷贝构造函数则编译器会给Date类生成一个默认的拷贝构造函数Date d2(d1);return 0;
} 注意在编译器生成的默认拷贝构造函数中内置类型是按照字节方式直接拷贝的而自定 义类型是调用其拷贝构造函数完成拷贝的。 我们不写编译默认生成的拷贝构造跟之前的构造函数特性不一样
内置类型 值拷贝自定义的类型调用它的拷贝
总结Date不需要我们实现拷贝构造默认生成就可以用 Stack需要我们自己实现深拷贝的拷贝构造默认生成会出问题
MyQueue对于默认生成的几个函数非常受用人生赢家 class MyQueue { private: Stack _pushst; Stack _popst; }; MyQueue mq1; MyQueue mq2 mq1; 编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了还需要自己显式实现吗 当然像日期类这样的类是没必要的。那么下面的类呢验证一下试试 // 这里会发现下面的程序会崩溃掉这里就需要我们以后学的深拷贝去解决。
typedef int DataType;
class Stack
{
public:Stack(size_t capacity 10){_array (DataType*)malloc(capacity * sizeof(DataType));if (nullptr _array){perror(malloc申请空间失败);return;}_size 0;_capacity capacity;}void Push(const DataType data){// CheckCapacity();_array[_size] data;_size;}~Stack(){if (_array){free(_array);_array nullptr;_capacity 0;_size 0;}}private:DataType* _array;size_t _size;size_t _capacity;
};int main()
{Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2(s1);return 0;
} 注意类中如果没有涉及资源申请时拷贝构造函数是否写都可以一旦涉及到资源申请 时则拷贝构造函数是一定要写的否则就是浅拷贝。 拷贝构造函数典型调用场景
使用已存在对象创建新对象 函数参数类型为类类型对象 函数返回值类型为类类型对象
class Date
{
public:Date(int year, int minute, int day){cout Date(int,int,int): this endl;}Date(const Date d){cout Date(const Date d): this endl;}~Date(){cout ~Date(): this endl;}
private:int _year;int _month;int _day;
};
Date Test(Date d)
{Date temp(d);return temp;
}
int main()
{Date d1(2022, 1, 13);Test(d1);return 0;
} 为了提高程序效率一般对象传参时尽量使用引用类型返回时根据实际场景能用引用尽量使用引用。 所有源代码如下 #includeiostream #includeassert.h using namespace std; 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(2023, 8, 9); d1.Print(); Date d2; d2.Init(2023, 8, 10); d2.Print(); return 0; } class Date { public: 无参构造函数 //Date() //{ // cout Date() endl; // _year 1; // _month 1; // _day 1; //} 带参构造函数 //Date(int year, int month, int day) //{ // cout Date(int year, int month, int day) endl; // _year year; // _month month; // _day day; //} //带参构造函数 Date(int year 1, int month 1, int day 1) { cout Date(int year, int month, int day) endl; _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.Print(); // 调用带参的构造函数 Date d2(2023, 8, 9); d2.Print(); // 注意如果通过无参构造函数创建对象时对象后面不用跟括号否则就成了函数声明 // 以下代码的函数声明了d3函数该函数无参返回一个日期类型的对象 // warning C4930: “Date d3(void)”: 未调用原型函数(是否是有意用变量定义的?) //Date d3(); //d3.Print(); Date d3(2023); d3.Print(); Date d4(2023, 8); d4.Print(); return 0; } class Stack { public: Stack(size_t n 4) { if (n 0) { a nullptr; top capacity 0; } else { a (int*)malloc(sizeof(int) * n); if(a nullptr) { perror(realloc fail); exit(-1); } top 0; capacity n; } } void Push(int x) { if (top capacity) { size_t newcapacity capacity 0 ? 4 : capacity * 2; int* tmp (int*)realloc(a, sizeof(int) * newcapacity); if (tmp nullptr) { perror(realloc fail); exit(-1); } if (tmp a) { cout capacity 原地扩容 endl; } else { cout capacity 异地扩容 endl; } a tmp; capacity newcapacity; } a[top] x; } int Top() { return a[top - 1]; } void Pop() { assert(top 0); --top; } void Destroy() { free(a); a nullptr; top capacity 0; } bool Empty() { return top 0; } private: // 成员变量 int* a; int top; int capacity; }; int main() { Stack st1; st1.Push(1); st1.Push(2); st1.Push(3); st1.Push(4); while (!st1.Empty()) { cout st1.Top() ; st1.Pop(); } cout endl; st1.Destroy(); Stack st2(1000); //Stack st2; for (size_t i 0; i 1000; i) { st2.Push(i); } while (!st2.Empty()) { cout st2.Top() ; st2.Pop(); } cout endl; st2.Destroy(); return 0; } class Date { public: 如果用户显式定义了构造函数编译器将不再生成 //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类中构造函数屏蔽后代码可以通过编译因为编译器生成了一个无参的默认构造函数 // 将Date类中构造函数放开代码编译失败因为一旦显式定义任何构造函数编译器将不再生成 // 无参构造函数放开后报错error C2512: “Date”: 没有合适的默认构造函数可用 Date d1; d1.Print(); return 0; } // 构造函数也是默认成员函数我们不写编译器会自动生成 // 编译生成的默认构造的特点 // 1、我们不写才会生成我们写了任意一个构造函数就不会生成了 // 2、内置类型的成员不会处理C11声明支持给缺省值 // 3、自定义类型的成员才会处理回去调用这个成员的默认构造函数 // 总结一般情况都需要我们自己写构造函数决定初始化方式 // 成员变量全是自定义类型可以考虑不写构造函数 class Time { public: Time() { cout Time() endl; _hour 0; _minute 0; _second 0; } private: int _hour; int _minute; int _second; }; class Date { private: // 基本类型(内置类型) int _year; int _month; int _day; // 自定义类型 Time _t; }; int main() { Date d; return 0; } class Time { public: Time() { cout Time() endl; _hour 0; _minute 0; _second 0; } private: int _hour; int _minute; int _second; }; class Date { private: // 基本类型(内置类型) int _year 1970; int _month 1; int _day 1; // 自定义类型 Time _t; }; int main() { Date d; return 0; } 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; }; // 以下测试函数能通过编译吗 void Test() { Date d1; } int main() { Test(); return 0; } class Date { public: Date(int year 1, int month 1, int day 1) { cout Date(int year 1, int month 1, int day 1) endl; _year year; _month month; _day day; } void Print() { cout _year / _month / _day endl; } ~Date() { cout ~Date() endl; } private: int _year 1; // 声明给的缺省值 int _month 1; int _day 1; }; class Stack { public: Stack(size_t n 4) { cout Stack(size_t n 4) endl; if (n 0) { a nullptr; top capacity 0; } else { a (int*)malloc(sizeof(int) * n); if (a nullptr) { perror(realloc fail); exit(-1); } top 0; capacity n; } } ~Stack() { cout ~Stack() endl; free(a); a nullptr; top capacity 0; } void Push(int x) { if (top capacity) { size_t newcapacity capacity 0 ? 4 : capacity * 2; int* tmp (int*)realloc(a, sizeof(int) * newcapacity); if (tmp nullptr) { perror(realloc fail); exit(-1); } if (tmp a) { cout capacity 原地扩容 endl; } else { cout capacity 异地扩容 endl; } a tmp; capacity newcapacity; } a[top] x; } int Top() { return a[top - 1]; } void Pop() { assert(top 0); --top; } void Destroy() { free(a); a nullptr; top capacity 0; } bool Empty() { return top 0; } private: // 成员变量 int* a; int top; int capacity; }; // 两个栈实现一个队列 class MyQueue { private: Stack _pushst; Stack _popst; }; int main() { Date d1; Date d2; Stack st1; Stack st2; return 0; } class Time { public: ~Time() { cout ~Time() endl; } private: int _hour; int _minute; int _second; }; class Date { private: // 基本类型(内置类型) int _year 1970; int _month 1; int _day 1; // 自定义类型 Time _t; }; int main() { Date d; return 0; } // 程序运行结束后输出~Time() // 在main函数中根本没有直接创建Time类的对象为什么最后会调用Time类的析构函数 // 因为main方法中创建了Date对象d而d中包含4个成员变量其中_year, _month, _day三个是 // 内置类型成员销毁时不需要资源清理最后系统直接将其内存回收即可而_t是Time类对象所以在 // d销毁时要将其内部包含的Time类的_t对象销毁所以要调用Time类的析构函数。但是main函数 // 中不能直接调用Time类的析构函数实际要释放的是Date类对象所以编译器会调用Date类的析构函 // 数而Date没有显式提供则编译器会给Date类生成一个默认的析构函数目的是在其内部调用Time // 类的析构函数即当Date对象销毁时要保证其内部每个自定义对象都可以正确销毁 // main函数中并没有直接调用Time类析构函数而是显式调用编译器为Date类生成的默认析构函数 // 注意创建哪个类的对象则调用该类的析构函数销毁那个类的对象则调用该类的析构函数 class Date { public: Date(int year 1, int month 1, int day 1) { _year year; _month month; _day day; } Date(Date d) { cout Date(Date d) endl; _year d._year; _month d._month; _day d._day; } void Print() { cout _year / _month / _day endl; } private: // 内置类型 int _year; int _month; int _day; }; 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; } Stack(Stack s) { cout Stack(Stack s) endl; // 深拷贝 _array (DataType*)malloc(sizeof(DataType) * s._capacity); if (NULL _array) { perror(malloc申请空间失败!!!); return; } memcpy(_array, s._array, sizeof(DataType) * s._size); _size s._size; _capacity s._capacity; } void Push(DataType data) { _array[_size] data; _size; } ~Stack() { cout ~Stack() endl; free(_array); _array nullptr; _size _capacity 0; } private: // 内置类型 DataType* _array; int _capacity; int _size; }; void func1(Date d) { d.Print(); } // 期望呢s要插入一些数据s的改变不影响s1 void func2(Stack s) { s.Push(1); s.Push(2); } int main() { Date d1(2023, 7, 21); func1(d1); Stack s1; func2(s1); Stack s2(s1); // 以下两个写法是等价的都是拷贝构造 Date d2(d1); Date d3 d1; return 0; } class Date { public: Date(int year 1900, int month 1, int day 1) { _year year; _month month; _day day; } // Date(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; Date d2(d1); return 0; } class Time { public: Time() { _hour 1; _minute 1; _second 1; } Time(const Time t) { _hour t._hour; _minute t._minute; _second t._second; cout Time::Time(const Time) endl; } private: int _hour; int _minute; int _second; }; class Date { private: // 基本类型(内置类型) int _year 1970; int _month 1; int _day 1; // 自定义类型 Time _t; }; int main() { Date d1; // 用已经存在的d1拷贝构造d2此处会调用Date类的拷贝构造函数 // 但Date类并没有显式定义拷贝构造函数则编译器会给Date类生成一个默认的拷贝构造函数 Date d2(d1); return 0; } // 这里会发现下面的程序会崩溃掉这里就需要我们以后学的深拷贝去解决。 typedef int DataType; class Stack { public: Stack(size_t capacity 10) { _array (DataType*)malloc(capacity * sizeof(DataType)); if (nullptr _array) { perror(malloc申请空间失败); return; } _size 0; _capacity capacity; } void Push(const DataType data) { // CheckCapacity(); _array[_size] data; _size; } ~Stack() { if (_array) { free(_array); _array nullptr; _capacity 0; _size 0; } } private: DataType* _array; size_t _size; size_t _capacity; }; int main() { Stack s1; s1.Push(1); s1.Push(2); s1.Push(3); s1.Push(4); Stack s2(s1); return 0; } class Date { public: Date(int year, int minute, int day) { cout Date(int,int,int): this endl; } Date(const Date d) { cout Date(const Date d): this endl; } ~Date() { cout ~Date(): this endl; } private: int _year; int _month; int _day; }; Date Test(Date d) { Date temp(d); return temp; } int main() { Date d1(2022, 1, 13); Test(d1); return 0; } 好啦小雅兰今天的学习内容就到这里啦还要继续加油噢
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/81554.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!