【C++】oop

视C++为一个语言联邦 ——《Effective C++》

oop是C++的一个重要部分,内容多且复杂。按照我脑海中现存有的知识结构结构总结一下

1、访问说明符

  一、类内部

  public:最开放的权限,即在类内部可以访问,对于该类的实例化像也能访问。

  private:最严格的权限,仅类内部和友元可以访问

  protected:可以视为public和private中和的产物,类内部可以访问,派生类内部可以访问(但是它只能访问派生类对象中基类对应的protected的部分,对于一个完全的基类的对象s,它是不能访问s中的protected的),类的实例化对象不能访问

  二、类派生列表中

  类派生列表中的访问说明符对类是没有影响的,它只会影响类的实例化对象。

2、构造、拷贝构造和析构函数

  一、调用子类构造函数和拷贝构造函数的过程发生了什么?

  调用子类构造函数时,它会先调用直接基类的构造函数,若直接基类还有基类,则继续调用间接基类的构造函数。

  二、调用子类析构函数的过程中发生了什么?

  它会先析构子类对象本身,再去调用基类的析构函数,以此类推,沿着集成体系的反方向进行

ps:对于类成员为用户定义类型的类来说,它的构造和析构过程和上面类似。构造过程:先构造类成员,成员构造完毕后,构造本身;析构过程:先析构本身,再析构成员。

3、继承和类型转换

  派生类可以向基类转换,但再这一过程中,派生类独有的成员会被slice down(切掉),反之不行。

  如果不想让某个类或类中的某个方法被继承,则可以使用关键字final

4、多态

  oop的一个重要特性,实质就是基类的指针可以指向派生类的对象

  一、静态类型和动态类型

  静态类型在编译时是已知的,它是变量声明时的类型,如 int s, string str;而动态类型直到运行时才知道,这叫做动态绑定。比如基类parent和它的派生类son,

  son s;parent *p = &s;这里p的静态类型是parent *, 所绑定对象的真实类型是son。因此,当使用基类的引用或指针时,我们并不清楚该指针或该引用所绑定对象的真实类型。该对象可能时基类,也可能时派生类。(直到运行时才确定下来)。但是,对非指针,非引用的普通对象来说,它们的静态类型始终等于动态类型。

  二、虚函数

  使用虚函数是为了使得派生类中的成员函数能够覆盖基类中的成员函数。

  基类中的虚函数必须用关键字virtual声明,而派生类中则可有可无;若派生类要对基类中的成员函数进行覆盖,则做好加上override关键字以显式声明。

  三、覆盖与隐藏

  先明确一个概念,派生类的作用域位于基类作用域之内,尽管他们在代码中是分离的。

  下面的代码中,派生类中的output()函数并不是对基类的覆盖,它只是对基类函数的隐藏,就好像同名的局部变量对全局变量的隐藏。在派生类的作用域内,它只看的见派生类的output()函数;因此,如果你声明了一个son类的对象s,s.output(), 它将会打印出son。然而,parent *ps = &s;ps->output(),它会打印出parent;

因为output不是虚函数,因此无法对它覆盖, 即它执行的是parent::output()。 

class parent {
public:
    int a;
    void output() {
        cout << "parent" << endl;
    }
};

class son :public parent {
public:
    int b;
    void output()  {
        cout << "son" << endl;
    }
};

而下面的代码就实现了对output()的覆盖

class parent {
public:
    int a;
    virtual void output() {
        cout << "parent" << endl;
    }
};

class son :public parent {
public:
    int b;
    void output() override {
        cout << "son" << endl;
    }
};

有了上面的代码,我们不管是对普通的son对象,还是绑定到son对象的parent指针,我们都可以使得它调用son::output()。

ps:对于一个基类的指针ps,即使ps绑定了派生类的对象,ps也不能调用派生类独有的成员。

  四、抽象基类

   纯虚函数:我们在基类中写了这个函数,但不想对他的函数体进行具体定义,而是想在派生类中对他进行覆盖。即这个函数在基类中是没有实际意义的。

  抽象基类:含有(或者未经覆盖直接继承)纯虚函数的类, 就好像java中接口的概念。抽象基类不能实例化对象。

猜你喜欢

转载自www.cnblogs.com/hhssqq9999/p/9123309.html