zoukankan      html  css  js  c++  java
  • 第十章 深入函数

    第十章 深入函数

    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 }
  • 相关阅读:
    Jackson学习资料
    servlet/filter/listener/interceptor区别与联系
    JDBC、JTA、Spring的事务管理
    hibernate 的SessionFactory的getCurrentSession 与 openSession() 的区别
    Spring MVC如何配置OpenSessionInViewInterceptor并结合Hibernate使用
    SpringMVC中使用Interceptor拦截器
    Hibernate条件查询
    Spring MVC之@RequestBody, @ResponseBody 详解
    Sping Environment为Null的原因和解决方法
    SpringMVC+Thymeleaf如何处理URL中的动态查询参数
  • 原文地址:https://www.cnblogs.com/zenseven/p/3734998.html
Copyright © 2011-2022 走看看