Loading

C++继承

继承

通过继承机制可以实现对代码的拓展以及重用,而不用通过复制粘贴的方式来实现重用

继承语法:Class B : public A{ ... }; public是公用继承用的最多,B是子类(派生类),A是父类(基类)

子类可以访问从父类被public修饰的成员变量和函数,以及一些新增加的函数和变量,子类不能直接访问父类的private修饰的成员。

虚函数:在类中声明成员函数为虚函数,是为了便于子类对父类函数的override(重写)

虚函数工作原理:通常编译器处理虚函数:给每个对象添加一个隐藏成员(vptr),隐藏成员(vptr)是一个指向函数地址数组的指针,这种数组成为虚函数表(virtual function table, vtbl)。虚函数表中存放的是为类对象进行声明的虚函数的地址。用《C++ Primer Plus》书中的例子来说明虚函数工作原理:

Physicist adam("Adam Crusher", "nuclear structre");
Scientist * psc = &adam;	//这里发生的是upcasting向上造型
psc->show_all();

psc->show_all()执行过程:

  1. 通过psc->vptr找到Physicist对象vptr中的值2096
  2. 通过地址2096找到对应的虚函数表
  3. 在表中寻找Physicist::show_all地址6820
  4. 跳转到地址6820去执行相应的函数

多态(Polymorphic):方法的行为取决于调用该方法的对象,同一个方法的行为随上下文而异。

实现多态的两种机制:

  • 父类函数添加virtual关键字
  • 子类中重写父类被virtual修饰的函数

纯虚函数(pure virtual functions):父类只有虚函数的声明,父类不能实例化,此时父类像是一个接口(interface),强制子类实现虚函数

举个例子:

声明一个抽象类Creature,让Animal类继承并实现其中的纯虚函数,Dog类再继承Animal类并重写play(),将Dog类对象、Animal类对象作为参数传递给void showPlay(Creature& c),会根据参数的类型选择其对应的函数。继承关系图:

#include <iostream>
using namespace std;

/******抽象类*******/
class Creature
{
public:
    virtual void sleep() = 0;   //pure virtual function
    virtual void eat() = 0;     //pure virtual function
    virtual void play() = 0;
};

/****************/

class Animal : public Creature
{
public:
    void sleep() { cout << "Animal is sleeping...\n"; }  
    void eat()  { cout << "Animal is eatting...\n"; }     
    virtual void play() { cout << "Animal is playing...\n"; }
};

class Dog : public Animal
{
private:
    double weight;
public:
    virtual void play() { cout << "Dog is playing...\n"; }	//重写父类的play(),C++11增加override关键字,增加可读性
    //也可以这么写:
    //virtual void play() override { cout << "Dog is playing...\n"; }
};

void showPlay(Creature& c)
{
    c.play();
}

int main()
{
    //Creature c; //报错,抽象类不能实例化
    Animal a;
    Dog d;
    showPlay(a);    //call Animal::play()
    showPlay(d);	//call Dog::play()

    return 0;
}
posted @ 2024-05-14 23:36  记录学习的Lyx  阅读(3)  评论(0编辑  收藏  举报