第十章 深入函数

第十章 深入函数

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 }
原文地址:https://www.cnblogs.com/zenseven/p/3734998.html