Giskard

(二十三)继承

2018-11-01

继承的概念

当类B继承于类A时,则A的部分成员在B类中自动获得。

class A
{

};
class B : public A
{

};

把A称为父类(基类),B为子类(派生类)

访问修饰符protected

  • 该成员不能被外界访问(包括main函数)
  • 该成员可以被子类继承

成员函数的重写

对于从父类继承过来的函数,子类可以重写一遍

class Base
{
protected:
    void Test()
    {
        printf("父类...\n");
    }
};
class Child : public Base
{
protected:
    void Test()
    {
        printf("子类...\n");
    }
};

Child ch;
ch.Test();
//执行结果:子类...

函数的增补

class Base
{
protected:
    void Test()
    {
        printf("父类...\n");
    }
};
class Child : public Base
{
protected:
    void Test()
    {
        Base::Test();   //先调用父类的代码
        printf("子类...\n");
    }
};

Child ch;
ch.Test();
//执行结果:
//父类...
//子类...

虚拟继承

  • 将父类指针指向子类对象
Base* p = new Child();
p->Test();

上述代码调用的是父类的Test还是子类的Test呢

运行一下发现实际执行的是Base::Test(),即父类的Test()

  • 虚函数virtual可以使输出结果为子类的Test()
class Base
{
protected:
    virtual void Test()
    {
        printf("父类...\n");
    }
};
class Child : public Base
{
protected:
    void Test()
    {
        printf("子类...\n");
    }
};

Base* p = new Child();
p->Test();
//执行结果:子类...

在继承关系中,父类的析构函数应该声明为virtual,否则执行

Base* p = new Child();
p->Test();

会调用父类的构造函数,这将导致严重的错误,因为子类没有被正确析构

构造函数前不能加virtual

继承关系下的构造与析构

当子类对象构造时,会先调用父类的构造函数,然后再执行自己的构造函数。当子类析构时,过程相反。

父类构造...
子类构造...
子类析构...
父类析构...

多重继承

一个类可同时继承于多个父类

class Child : public Father,public Mother
{

};

该语法有明显缺陷,当Father中的成员变量与Mother中有重名时,会使问题变得复杂。

*纯虚函数/抽象函数

class CmdHandler
{
public:
    virtual void Oncommand(char* cmdline) = 0; //后面加上 = 0
}

CmdHandler handler;//错误!!抽象类不能实例化

纯虚类/抽象类不能被实例化,定义它的作用是什么?

用于实现设计模式里的接口概念,相当于Java中的interface语法,不需要详细了解。

Tags: C/C++