zoukankan      html  css  js  c++  java
  • 第二章 掌握C++(2)C++的特性(上)

    新建一个win32控制台应用程序,选择空项目。

      

    #include <iostream>
    using namespace std;
    
    class point
    {
    public:
        int x;
        int y;
        void output()
        {
            cout<<x<<" "<<y<<endl;
        }
    };
    
    int main()
    {
        point pt;
        
        pt.output();
    
        system("pause");//暂停作用
        return 0;
    }

      运行上述代码。上述代码我们定义了一个point类,在main函数中定义了一个pt对象,它的类型是point这个类。

      什么是类?什么是对象?

      2.2.1类与对象

      类描述了一类事物,以及事物所应具有的属性。例如,我们可以定义“电脑”这个类,那么作为“电脑”这个类,它应该具有显示器、主板、CPU、内存、硬盘等等。那么什么是“电脑”对象呢?例如我们组装了一台具体的电脑,它的显示器是美格的,主板是华硕的,CPU是Intel的,内存是现代的,硬盘用的是希捷的,也就是“电脑”这个类所定义的属性,在我们购买的这台具体的电脑中,有了具体的值。这台具体的电脑就是我们“电脑”这个类的一个对象。“类的实例”和“类的对象”是一个概念。对象是可以销毁的。而类是不能被损毁的。例如我们可以损毁我们购买的这台具体的电脑,却不能毁掉“电脑”这个抽象的概念。

      2.2.2构造函数

      运行上述代码,会出现下图的情况。

      因为,我们在构造pt对象的时候,系统为它的成员变量x和y分配内存空间,而这个内存空间中的值是一个随机值。但是作为一个坐标点,我们都希望它们能有正常一点的值。所以需要一个初始化函数。

    #include <iostream>
    using namespace std;
    
    class point
    {
    public:
        int x;
        int y;
        void init()//初始化函数
        {
            x = 0;
            y = 0;
        }
        void output()
        {
            cout<<x<<" "<<y<<endl;
        }
    };
    
    int main()
    {
        point pt;
        pt.init();//初始化
        pt.output();
    
        system("pause");//暂停作用
        return 0;
    }

      对于这个定义的初始化函数,我们在写程序的时候或许会忘记调用它。所以,构造函数就出场啦。

      构造函数的名字和类名相同,没有返回值。将上述代码改为构造函数的是:

    #include <iostream>
    using namespace std;
    
    class point
    {
    public:
        int x;
        int y;
        point()//构造函数,当定义对象的时候自行调用。
        {
            x = 0;
            y = 0;
        }
        void output()
        {
            cout<<x<<" "<<y<<endl;
        }
    };
    
    int main()
    {
        point pt;
    
        pt.output();
    
        system("pause");//暂停作用
        return 0;
    }

      运行结果是:

      构造函数的作用是对对象本身做初始化工作,也就是给用户提供初始化类中成员变量的一种方式。如果一个类中没有定义构造函数,那么C++编译器在某些情况下会为该类提供一个默认的构造函数,这个默认的构造函数是一个不带参数的构造函数。只要一个类中定义了一个构造函数,不管这个构造函数是否是带参数的构造函数,C++编译器就不在提供默认的狗杂函数。也就是说,如果一个类定义了一个带参数的构造函数,还想要一个无参数的构造函数,则必须自己定义

      2.2.3析构函数

      在一个对象生命周期结束时,应用析构函数来释放这个对象所占有的资源。一般定义为~类名(),例如:~point()。析构函数不允许带参数,且一个类中只有一个析构函数。

      根据析构函数的特点,可以在构造函数中初始化对象的某些成员变量,为其分配内存空间(堆内存),在析构函数中释放这些资源。

    #include <iostream>
    using namespace std;
    
    class point
    {
    public:
        int x;
        int y;
        char *pPointName;//点的别名
        point()
        {
            x = 0;
            y = 0;
            pPointName = new char[20];//申请内存空间
        }
    
        void output()
        {
            cout<<pPointName<<"("<<x<<","<<y<<")"<<endl;
        }
    
        ~point()//析构函数
        {
            delete[] pPointName;//释放内存空间
        }
    };
    
    int main()
    {
        point pt;
        pt.pPointName="起点";
        pt.output();
    
        system("pause");//暂停作用
        return 0;
    }

      在上述代码中,给字符指针变量pPointName在堆上分配了20个字符的内存空间,在析构函数中调用delete,释放在堆上分配的内存。如果没有delete[] pPointName;这句代码,当我们定义一个point类对象,在这个对象声明周期结束时,它的构造函数中分配的这块内存就会丢失,造成内存泄露。

      在类中定义成员变量时,不能直接给成员变量赋初值

      2.2.4函数的重载

      如果我们希望在构造pt这个对象的同时,传递x,y坐标值。可以再定义一个构造函数。

      

    #include <iostream>
    using namespace std;
    
    class point
    {
    public:
        int x;
        int y;
        char *pPointName;//点的别名
        point()
        {
            x = 0;
            y = 0;
            pPointName = new char[20];//申请内存空间
        }
        point(int x , int y)//新的构造函数
        {
            x = x;
            y = y;
        }
    
        void output()
        {
            cout<<pPointName<<"("<<x<<","<<y<<")"<<endl;
        }
    
        ~point()//析构函数
        {
            delete[] pPointName;//释放内存空间
        }
    };
    
    int main()
    {
        point pt(5,5);
        pt.pPointName="起点";
        
        pt.output();
    
        system("pause");//暂停作用
        return 0;
    }

      可是运行结果并非预料的“起点(5,5)”,而是

      原因在新的构造函数中,类的成员变量x和y是没有作用域的,它们的作用域被形参x和y覆盖了。那么解决这一问题的办法有两个:第一,更改形参的名称;第二,用this指针。

    point(int ptx , int pty)//新的构造函数
    {
        x = ptx;
        y = pty;
    }

      或者:

    point(int x , int y)//新的构造函数
    {
        this->x = x;
        this->y = y;
    }

      再次运行时候,就会运行成功。

      在这个程序中有两个构造函数。它们的函数名称是一样的,只是参数的类型和个数不一样。在C语言中是不允许这样的,可是在C++中是合法的,这叫做函数的重载(overload)。重载函数的条件:函数的参数类型、参数个数不同只有函数的返回类型不同是不能够构成重载函数的

      然而,下面的也不成为重载函数。

    void output(int a,int b=5);
    void output(int a);

      当我们在程序中调用output(5)的时候,调用第一个和第二个函数都是可以的,因为第一个函数的第二个参数有默认值,它的第二个参数是可以略去不写的。由于调用有歧义,所以不构成重载。

      2.2.5this指针

      在2.2.4我们提到了this指针,它能够解决类成员变量和函数参数变量名字冲突时候的变量作用域问题,是为什么呢?

      其实this是一个隐含的指针,它指向对象本身,代表了对象的地址。在调用函数的时候除了接收参数外,还接收到了pt对象的地址,这个地址被一个隐含的形参this指针所获取,等同于this = &pt。所以就将本来区分不请的参数们区分开来了。

      

      

  • 相关阅读:
    Android之SurfaceView学习(一)
    AS3的加载机制(带例子) 转载
    Timer与TimerTask的用法
    A*寻路初探 GameDev.net (转载)
    解决在Sql Server2005查询分析器中读取Excel表出现的一些问题
    svn更改用户问题
    MVC4 WEBAPI初探
    使用WORD2013发布blog
    一个IIS中可否支持两个版本的Freamwork
    web打印也能分页
  • 原文地址:https://www.cnblogs.com/xueniwawa/p/3999615.html
Copyright © 2011-2022 走看看