(Boolan)面向对象高级编程(上)第三周笔记

一、基本概念

1、类的继承,是新的类从已有类那里得到已有的特性。 或从已有类产生新类的过程就是类的派生。 原有的类称为基类或父类,产生的新类称为派生类或子类。

2、派生类的声明:

class 派生类名:继承方式 基类名1, 继承方式 基类名2,...,继承方式 基类名n

{

派生类成员声明;

};

3、一个派生类可以同时有多个基类,这种情况称为多重继承,派生类只有一个基类,称为单继承。 直接派生,间接派生。

4、继承方式规定了如何访问基类继承的成员。 继承方式有public, private, protected。 如果不显示给出继承方式,默认为private继承。 继承方式指定了派生类成员以及类外对象对于从基类继承来的成员的访问权限。

5、派生类继承基类中除构造和析构函数以外的所有成员。

6、派生类生成:

吸收基类成员(除构造析构函数以外的所有成员);

改造基类成员(根据继承方式调整基类成员的访问,函数在子类中的覆盖,以及虚函数在子类中的覆盖);

添加新的成员;

注:C++类的3种继承方式,分别是public继承,protected继承,private继承。

最常用的还是public继承。 class默认的是private继承,它的member如果没写权限也是默认

private。 struct则相反,默认的是public继承。

二、例子:

3个继承权限的区别:

class ex0

{

private:

void showPrivate(){cout<<"this is private function!";}

public:

void showPublic(){cout<<"this is public function!";}

protected:

void showProtected(){cout<<"this is protected function!";}

};

class ex1:public ex0

{

public:

void func()

{

showPrivate();

//错误因为此函数访问权限只有基类 ex0 自己有

showPublic();

showProtected();

}

};

class ex2:protected ex0

{

public:

void func()

{

showPrivate();

//错误因为此函数访问权限只有基类 ex0 自己有

showPublic();

//正确, 但是此函数由于 ex2 的保护继承这个函数的访问权限已经变成了 protected,

//也就是说对于外部类来说已经不具备访问这个函数的权限了

showProtected();

}

};

class ex3:private ex0

{

public:

void func()

{

showPrivate();

//错误因为此函数访问权限只有基类 ex0 自己有

showPublic();

//正确, 但是此函数由于 ex3 的私有继承这个函数的访问权限已经变成了 private,

//也就是说对于外部类和派生类来说已经不具备访问这个函数的权限了

showProtected();

//正确, 但是此函数由于 ex3 的私有继承这个函数的访问权限已经变成了 private,

//也就是说对于外部类和派生类来说已经不具备访问这个函数的权限了

}

};

三、虚函数表解析

1.简介

C++中的虚函数的作用主要是实现了多态。

多态就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。 这种技术可以让父类的指针有“多种形态”,是一种泛型技术。

泛型技术指试图使用不变的代码来实现可变的算法。

2.虚函数表

虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。 简称为V-Table。

在这个表中,主是要一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其真实反应实际的函数。 这样,在有虚函数的类的实例中这个表被分配在了 这个实例的内存中,所以,当我们用父类的指针来操作一个子类的时候,这张虚函数表就显得由为重要了,它就像一个地图一样,指明了实际所应该调用的函数。

编译器必需要保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证正确取到虚函数的偏移量)。 这意味着我们通过对象实例的地址得到这张虚函数表,然后就可以遍历其中函数指针,并调用相应的函数。

假设有下面这个类:

class Base {

public:

    virtual void f( ) { cout << "Base::f" << endl; }

    virtual void g( ) { cout << "Base::g" << endl; }

    virtual void h( ) { cout << "Base::h" << endl; }

};

我们可以通过Base的实例来得到虚函数表。

    Base b;

    cout << "虚函数表地址:" << (int*)(&b) << endl;

    cout << "虚函数表 — 第一个函数地址:" << (int*)*(int*)(&b) << endl;

可得到:

虚函数表地址:0012FED4

虚函数表 — 第一个函数地址:0044F148

你可能感兴趣的:((Boolan)面向对象高级编程(上)第三周笔记)