用了这么久C++,到头来才发现很多基础的东西搞的不够透彻,借此机会巩固一下。
    首先看一看C++的三大特性:封装性、继承性、多态性
    1.封装性
        封装性使得程序更加结构化,并且可以通过访问权限保护数据成员。
        C++中结构体和类实际上是同一种东西,在结构体中也可以定义方法,也可以使用权限标识符。两者有两个不同点:
        (1)关键字不同,一个是struct,一个是class
        (2)成员的默认访问权限不同,结构体的默认访问权限是public,而类的默认访问权限是private
    2.继承性
        用":"表示继承关系,继承方式有三种,默认为protected继承方式:
        (1)public:父类的public、protected权限的成员在子类中的访问权限保持不变
        (2)protected:父类的public、protected权限的成员在子类中的访问权限均变为protected
        (3)private:父类的public、protected权限的成员在子类中的访问权限均变为private
        无论哪种继承方式,父类的private方法都无法被子类访问
    3.多态性
    在写程序的时候,一个父类会有很多子类,现在如果要写一个通用的函数,参数为该类的对象的指针,那么很显然,我们不希望为每个子类都写一个这样的函数,那样就太麻烦了。能不能只写一个关于父类的函数,而传递参数时传递子类的对象,让该函数自己判断传入对象的类型,然后调用正确的方法呢?答案是可以的,这就是“迟绑定”技术。要实现“迟绑定”,只需要在父类中把需要调用的函数声明为virtual就可以了。
    比如下面这个函数:
    void fn(Animal *pAn)
    {
         pAn->eat();
    }
    Fish是Animal类的一个子类,eat()是Animal中声明的一个虚函数,如果传递Fish对象给函数fn,那么在程序运行时,将会把eat()绑定到Fish对象的eat()方法上,如果Fish类中没有覆盖eat()方法,那么就会绑定到父类Animal的eat()方法。
    注意:
    (1)如果没有声明为virtual方法,那么fn函数将把Fish对象强制转换为Animal对象,这样调用的就是Animal对象的eat()方法,而不是调用Fish对象的eat()方法了。
    (2)可以只在父类中声明函数,而不实现,这样该函数就成为一个纯虚函数:
        virtual void eat() = 0;
    而父类就变成一个抽象类,不能实例化对象,子类必须实现纯虚方法。


    下面再看看C++中的一些其他的重要的特性。
    4.函数重载
    如果要实现一个通用的加法函数add,在C语言中必须针对不同的数据类型构造不同的函数,如:
        addInt(int x, int y);
        addFloat(float x, float y);
        ...

    这样就需要记忆很多的函数名,造成了函数接口的不统一。在C++中允许不改变函数名,只改变参数类型,来实现函数的重载,有效的解决了这个问题:
        add(int x, int y);
        add(float x, float y);
        ...

    重载与返回值无关,函数名相同但返回值不同的两个函数是无法通过编译的。
    5.函数的覆盖
    这个要和函数重载区分开,函数的覆盖指的是在子类中重写父类中定义的方法。
    6.引用与指针
    引用就是一个变量的别名,指的是同一块内存区域,本身不占内存空间;而指针存放的是变量的地址,本身要占据4个字节的空间。
    引用必须在定义时就赋值,并且以后不能更改所引用的变量;而指针可以存放任意变量的地址,可以随时改变。
在传递函数参数时,有时候引用类型比指针类型看起来更直观,更能表现函数所表达的意思,如:
    void swap(int *pA, int *pB)
    {
         int temp;
         temp = *pA;
         *pA = *pB;
         *pB = temp;
    }

    调用:swap(&x, &y);//需要传递变量的地址

    void swap(int &a, int &b)
    {
         int temp;
         temp = a;
         a = b;
         b = temp;
    }

    调用:swap(x, y);//直接传递变量的引用
    7.构造函数和析构函数
    只需要注意一下父类和子类构造函数和析构函数的调用顺序:
        分配内存空间时先调用父类的构造函数,再调用子类的构造函数
        释放内存空间时先调用子类的析构函数,再调用父类的析构函数
    8.this指针
    一个类的所有对象所调用的成员函数都是同一代码段,不同对象调用成员函数时将传递一个隐含的形参:this指针,对所有数据成员的访问都隐式的被加上this->。