Loading

浅谈 C++ 继承

继承

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

继承可以扩展已存在的代码,目的也是为了代码重用,继承方式限定了基类成员在派生类中的访问权限,包括 public(公有的)、private(私有的)和 protected(受保护的)。其权限如下图所示:

下面是一个时钟的例子。

#include <iostream>
using namespace std;

class Clock
{
public:
    Clock(int h = 0, int m = 0, int s = 0) : hour(h), minute(m), second(s)
    {
        cout << "This is the Clock's constructor" << endl;
    }

    Clock(const Clock &other) : hour(other.hour), minute(other.minute), second(other.second)
    {
        cout << "This is the Clock's copy constructor" << endl;
    }

    ~Clock()
    {
        cout << "This is the Clock's destructor" << endl;
    }

    void showTime()
    {
        cout << hour << ":" << minute << ":" << second << endl;
    }

    void setTime(int h, int m, int s)
    {
        hour = h;
        minute = m;
        second = s;
    }

private:
    int hour;
    int minute;
    int second;
};

class CalendarClock : public Clock
{
public:
    CalendarClock(int y, int M, int d, int h, int m, int s) : Clock(h, m, s), year(y), month(M), day(d)
    {
        cout << "This is the CalendarClock's constructor" << endl;
    }

    CalendarClock(const CalendarClock &other) : Clock(other), year(other.year), month(other.month), day(other.day)
    {
        cout << "This is the CalendarClock's copy constructor" << endl;
    }

    void show()
    {
        cout << year << "-" << month << "-" << day << " ";
        Clock::showTime();
    }

    void setTime(int y, int M, int d, int h, int m, int s)
    {
        Clock::setTime(h, m, s);
        year = y;
        month = M;
        day = d;
    }

    ~CalendarClock()
    {
        cout << "This is the CalendarClock's destructor" << endl;
    }

private:
    int year;
    int month;
    int day;
};

int main(void)
{
    CalendarClock c(2020,10,5,9,57,5);
    c.show();
    Clock *p = &c;
    p->showTime();
    system("pause");
    return 0;
}

虚基类

为了解决多继承时的命名冲突和冗余数据问题,C++ 提出了虚继承,使得在派生类中只保留一份间接基类的成员。

在继承方式前面加上 virtual 关键字就是虚继承。如果遇见sizeof,一个 virtual +4 ,然后去掉重复的部分。

构造函数执行的流程为:
1、传参
2、执行直接或者间接虚基类构造
3、执行直接基类构造
4、为数据成员开辟空间
5、执行构造函数函数体

下面是一道考题:

#include <iostream>
using namespace std;

class Base
{
public:
    Base(int i) { cout << i; }
   ~Base() { }
};

class Base1: virtual public Base
{
public:
    Base1(int i, int j = 0) : Base(j) { cout << i; }
   ~Base1() {}
};

class Base2: virtual public Base
{
public:
    Base2(int i, int j = 0) : Base(j) { cout << i; }
   ~Base2() {}
};

class Derived : public Base2, public Base1
{
public:
   Derived(int a, int b, int c, int d) : Base(a), Base2(d), Base1(c), mem2(b), mem1(a) { cout << b; }
private:
   Base2 mem2;
   Base1 mem1;
};

int main(void)
{
   Derived objD (1, 2, 3, 4);
}

仔细思考一下,先初始化虚基类,输出1;
然后按“public Base2, public Base1”的顺序,先初始化Base2,再初始化Base1,输出43;
再初始化mem2,输出02;接着初始化mem1,输出01;最后执行{}里的语句,输出2。

posted @ 2020-10-05 20:56  小森林呐  阅读(207)  评论(0编辑  收藏  举报