第十章 深入函数
1. 普通函数的重载
将相同名字不同类型的函数重复调用多次来处理不同类型的数据
①根据参数类型不同进行重载
②根据参数个数不同进行重载
☆1.1
重载 | 覆盖 | 隐藏 | |
共同点: | 函数名相同 | 函数名相同 | 函数名相同 |
不同点: |
同类、参数类型、数量不同 或 有无const |
不同类,同参,有基virtual |
不同类,同参,且无virtual 不同类,不同参(不论有无virtual) |
体现: | 由函数调用(静态联编) | 由函数调用取决于object(动态联编) | 取决于pointer(不能体现多态性) |
2. 函数的缺省参数
☆可见函数重载主要是根据参数进行重载
(函数都可以被重载)
3. 重载构造函数
4. 成员变量的初始化
有两种方法
①函数体内
②函数体外(可用于常量和引用的初始化)
Rectangle (): length (7), width (8) {}
1 #include "iostream" 2 using namespace std; 3 class A 4 { 5 private: 6 const int num; 7 int &total; 8 public: 9 //A(int a, int b){num=a;&total=b;}//错 10 A(int a, int b):num(a),total(b){} 11 }; 12 int main() 13 { 14 return 0; 15 }
5. 成员变量的初始化与构造函数
构造函数的构造顺序是按(成员列表)的顺序进行,而析构函数的析构顺序与构造函数相反
6. 复制构造函数
A(A &one){n=one.n;m=one.m} one是要复制的对象的别名
按值传递时会调用复制构造函数
7. 构造函数和NEW运算符
8. 再谈默认构造函数
假如你创建了一个构造函数 编译器就不会为你提供默认构造函数(如果想要就必须自己创)
9. 析构函数和delete运算符
delete 函数能自动调用析构函数删除new运算符创建的内存空间
10. 默认析构函数
当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数。 分两种:栈中 遇return等。堆中 delete。
11. 调用构造函数进行类型转换
explicit A(int x){}//关键explicit放在构造函数前,用于关闭隐式转换
A a(23); //常规写法
a=A(1000);//显示转换
a=1000; //隐式转化 有explicit 不能用
12. 浅层复制构造函数
13. 深层复制构造函数
引用复制构造函数的原因:当A类复制构造函数的成员变量有指针。B=A;就相当于两个对象的指针指向一个内存;当delete A;就告诉编译器此内存可用了;也就相当于delete B了;就会出现迷途指针B.x;这不符合用户意愿;(所谓迷途指针就是指向未知区域的指针。所以指针在被delete之后一定要指向NULL或者指向一个已知的区域)
深层复制构造函数要为新对象重新开辟内存
1 //深层复制构造函数 2 #include"iostream" 3 using namespace std; 4 5 class A 6 { 7 private: 8 int *a; 9 int b; 10 public: 11 A(int j){a=new int(j);} 12 ~A(){cout<<"析构函数执行。。。"<<endl;delete a;a=NULL;} 13 A(const A &r) 14 { 15 cout<<"复制构造函数执行。。。"<<endl; 16 a=new int; 17 *(this->a)=*(r.a); //值的复制 18 } 19 int print()const{return *a;} 20 void set(int x){b=x;} 21 }; 22 int main() 23 { 24 A Object1(7); 25 A Object2(1); 26 cout<<Object1.print()<<endl; 27 cout<<Object2.print()<<endl; 28 A Object3=Object2;//要分清复制/赋值构造函数 29 cout<<Object3.print()<<endl; 30 return 0; 31 }
本章总结:
1. 函数的重载主要通过参数(类型,个数)进行
2. 成员变量的初始化
① 构造函数体内{}
② 构造函数体外:rectangle():length(7),width(8){}
rectangle(int i ,int j ,int k):x(i),length(j),width(k){}
3. 构造函数的构造顺序是按成员列表的顺序进行,析构则相反
4. 调用构造函数进行类型转换
A(int x){}
//explicit A(int x){}//explicit用于关闭隐式转换。但,只能对有参构造函数起作用
void main()
{
A a(23);
a=A(1000);//显示转换
a=1000;//隐式转换
}
5. 浅层复制:复制的是地址(两个指针指向同一个地址);深层复制:复制的是数值(再开辟一个新空间)
1 #include"iostream" 2 using namespace std; 3 class A 4 { 5 //函数重载主要依据参数类型、以及参数个数的不同进行!**********************① 6 //函数的默认参数:void func(int=1,int=2);//函数声明部分*********************② 7 /* 8 public: 9 //A(int x, int y){num=x;&total=y;}//const以及引用不能用,常量以及引用只能初始化不能被赋值****************③ 10 A(int x, int y):total(y),num(x){}//先给num赋值,以为是按声明的顺序**************************④ 11 private: 12 const int num; 13 int &total; 14 */ 15 16 /* 17 //**************************???????????????????????此处的const为什么没有报错 18 public: 19 void set(const int =2,const int =3); 20 private: 21 int w; 22 int h; 23 */ 24 25 /* 26 //调用构造函数进行类型转换 27 28 explicit A(int x){} 29 A a(23); 30 a=A(1000);//显示转换 31 a=500;//隐式转换 有explicit就不能用 32 33 */ 34 35 public: 36 A(){x=new int;*x=5;} 37 ~A(){delete x;x=NULL;cout<<"析构函数调用中。。。"<<endl;} 38 A(const A&r) 39 { 40 cout<<"复制构造函数执行..."<<endl; 41 x=new int; 42 *(this->x)=*(r.x);//深层复制构造函数,避免了两个对象指向同一个栈中空间 43 } 44 int get()const{return *x;} 45 void set(int i){*x=i;} 46 private: 47 int* x; 48 49 }; 50 //void A::set(const int width,const int height){w=width;h=height;} 51 52 int main() 53 { 54 A *a1=new A; 55 cout<<"a1:"<<a1->get()<<endl; 56 A b1=(*a1);//初始化时调用复制构造函数,赋值时调用复制操作符*********************⑤ 57 a1->set(32); 58 cout<<"b1:"<<b1.get()<<endl; 59 b1.set(99); 60 cout<<"a1:"<<a1->get()<<endl; 61 cout<<"b1:"<<b1.get()<<endl; 62 delete a1;//??????????????????????析构函数 63 64 65 66 /* 67 A a; 68 A b; 69 a.set(3,4); 70 b.set(5,6); 71 */ 72 73 return 0; 74 75 }
1 //深层复制的例程如下: 2 #include <iostream> 3 using namespace std; 4 class A 5 { 6 public: 7 A(){x=new int;*x=5;} //创建一个对象的同时将成员指针指向的变量保存到新空间中 8 ~A(){delete x;x = NULL;cout<<"析构函数执行... "<<endl;} //析构对象的同时删除成员指针指向的内存空间,// 为了稳妥起见将指针赋为空 9 A(const A &a) 10 { 11 cout << "复制构造函数执行... " <<endl; 12 this->x=new int; //复制构造对象的同时将成员指针指向的变量保存到新空间中 13 *(this->x) = *(a.x); //读取旧对象的成员指针x指向的空间处的数据并赋给新对象的成员指针x所指向的内存区域 14 } 15 int print()const{return *x;} 16 void set(int i){*x=i;} 17 private: 18 int *x; 19 }; 20 int main() 21 { 22 A *a = new A(); 23 cout<<"a:"<<a->print()<<endl; 24 A b=(*a);//用已有对象创建一个对象调用复制构造函数*************************① 25 //A b; 26 //b=(*a);//这会调用赋值操作符,重载函数 27 a->set(32); 28 cout<<"b:"<<b.print()<<endl; 29 b.set(99); 30 cout<<"a:"<<a->print()<<endl; 31 delete a; 32 return 0; 33 }