3.初始化列表解决的三大问题
(1)类中的引用成员变量
引用在定义的时候必须初始化,否则会出现编译错误,详见重生之我要学C++第二天_无极太族的博客-CSDN博客
类中的成员都是在初始化列表中定义的,如果成员有引用类型就必须在初始化列表中初始化。
1. #include<iostream> 2. using namespace std; 3. class A 4. { 5. public : 6. A(int a) 7. { 8. _a = a;//初始化 9. } 10. private: 11. int& _a; 12. }; 13. int main() 14. { 15. int tmp = 2; 16. A a(tmp); 17. return 0; 18. }
此时,引用_a的定义在默认初始化列表中已经完成,在构造函数函数体中在赋值初始化会导致编译错误(定义处未初始化)。
解决方案:在构造函数中手动添加初始化列表,在初始化列表中定义和初始化一并进行。
1. A(int a) 2. : 3. _a(a) 4. { 5. 6. }
(2)const成员变量
const成员变量容易出问题和引用的原理相同。都是定义处必须初始化。
(3)自定义类型成员没有默认构造函数时的问题
我们知道,构造函数不写初始化列表时,默认初始化列表会调用自定义类型的默认构造函数
默认构造函数:
详见:重生之我要学C++第四天_无极太族的博客-CSDN博客
但是如果此时这个自定义类型没有默认构造方法,会出现编译错误。
这时候就必须手动添加参数列表,选择性的调用自定义类型具有的构造方法。
运算符重载的应用
第四天我们学习了运算符重载,在这里举两个例子让读者感受到运算符重载的魅力!
(1)顺序表中的运算符重载
先写一个简陋的顺序表
1. #include<iostream> 2. using namespace std; 3. class Sequence 4. { 5. public: 6. Sequence() 7. { 8. //初始化 9. _a = (int*)malloc(4 * sizeof(int)); 10. _size = 0; 11. _capcity = 4; 12. } 13. void Push(int x) 14. { 15. //检查容量:此处忽略 16. 17. _a[_size] = x; 18. _size++; 19. } 20. void Print() 21. { 22. for (int i = 0; i < _size; i++) 23. { 24. cout << _a[i] << " "; 25. } 26. } 27. private: 28. int* _a; 29. int _size; 30. int _capcity; 31. }; 32. int main() 33. { 34. Sequence s;//创建顺序表 35. s.Push(1);//尾插三个数据 36. s.Push(2); 37. s.Push(3); 38. //打印顺序表 39. s.Print(); 40. return 0; 41. }
我们可以在类内部将[ ]重载一下
1. int& operator[](int i) 2. { 3. return _a[i]; 4. }
此时,顺序表内的元素就可以像数组一样访问:
1. int main() 2. { 3. Sequence s;//创建顺序表 4. s.Push(1);//尾插三个数据 5. s.Push(2); 6. s.Push(3); 7. 8. //打印顺序表 9. cout << s[0]<<s[1]<<s[2]<<endl; 10. return 0; 11. }
重载[ ]后,可以让顺序表更加形象,大大增强了代码的可读性。
(2)自定义类型的流插入流提取
用Date类来举例
1. #include<iostream> 2. using namespace std; 3. class Date//类Date 4. { 5. public: 6. Date(int year=1, int month=1, int day=1)//构造函数 7. { 8. _year = year; 9. _month = month; 10. _day = day; 11. } 12. void Print() 13. { 14. cout << _year << "年" << _month << "月" << _day << "天" << endl; 15. } 16. private: 17. //成员变量的声明 18. int _year;//内置类型成员 19. int _month; 20. int _day; 21. }; 22. int main() 23. { 24. Date d1(1,1,2); 25. d1.Print(); 26. return 0; 27. }
可以使用Print函数来打印日期
但是如果这样也可以打印日期,是不是会觉得赏心悦目
cout<<d1<<endl;
下面我们就利用运算符重载来实现这个想法。
1. #include<iostream> 2. using namespace std; 3. 4. class Date//类Date 5. { 6. public: 7. friend ostream& operator<<(ostream& out, Date& d);//将此函数声明为类Date的友元函数 8. Date(int year=1, int month=1, int day=1)//构造函数 9. { 10. _year = year; 11. _month = month; 12. _day = day; 13. } 14. void Print() 15. { 16. cout << _year << "年" << _month << "月" << _day << "天" << endl; 17. } 18. private: 19. //成员变量的声明 20. int _year;//内置类型成员 21. int _month; 22. int _day; 23. }; 24. ostream& operator<<(ostream& out, Date& d) 25. { 26. out << d._year << "年" << d._month << "月" << d._day << "天"; 27. return out; 28. } 29. int main() 30. { 31. Date d1(1, 1, 2); 32. cout << d1; 33. 34. return 0; 35. }
运行结果:
这里cout是ostream类的对象,将运算符重载写为全局函数就可以调换cout对象和d对象的位置。使用友元函数使得在类外面的函数可以访问类的private成员。下篇文章会介绍友元函数。
今天的分享就到这里啦,如果对大家有用的话,希望程序猿们可以三连支持一下,会继续分享知识!谢谢!