迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 > C++ >

C++ 子类继承

作者:迹忆客 最近更新:2023/08/22 浏览次数:

继承是 OOP 的一个特性,其中一个类获取另一个类的属性和行为。 继承另一个类的类称为子类,而其属性被继承的类称为基类。

本文将讨论继承类时出现的钻石问题。


C++ 子类继承

继承是一种让一个类继承另一个类的属性的功能。 继承另一个类的属性的类称为子类或派生类,而继承其属性的类称为基类或父类。

现实世界中继承的一个例子是孩子继承其父母的财产。

C++中的继承主要有五种类型,即单继承、多重继承、多级继承、层次继承和混合继承。

  1. 单一继承 - 在这种类型的继承中,单个子类继承自单个基类。
  2. 多重继承 - 在这种类型的继承中,子类是从多个基类继承的。
  3. 分层继承 - 在这种类型的继承中,多个子类从同一个基类继承。
  4. 多级继承 - 在这种类型的继承中,一个类被另一个类继承,而另一个类又被其他一些类继承。 比如我们有A、B、C三个类,其中C类被B类继承,B类被A类继承。
  5. 混合继承 - 在这种类型的继承中,组合了多种类型的继承。

我们首先讨论C++中的多重继承和层次继承。


C++ 子类的多重继承

如前所述,在多重继承中,子类被多个其他基类继承。 让我们举个例子来详细理解多重继承。

#include<iostream>
using namespace std;
class Base1
{
    public:
        Base1() {
            cout << "Base class 1" << endl;
        }
};

class Base2
{
    public:
        Base2() {
            cout << "Base class 2" << endl;
        }
};

class Derived: public Base2, public Base1
{
    public:
        Derived() {
            cout << "Derived class" << endl;
        }
};

int main()
{
  Derived d;
  return 0;
}

输出:

Base class 2
Base class 1
Derived class

上面的代码有两个基类Base1和Base2,Derived类继承自这两个基类。 但是,您必须注意基类构造函数的调用顺序。

首先,调用 Base2 类构造函数,因为 Derived 类首先继承它,然后调用 Base1 构造函数。


C++中子类的层次继承

如前所述,在层次继承中,多个子类是从单个基类继承的。 我们通过一个例子来详细了解一下层次继承。

#include<iostream>
using namespace std;
class Base
{
    public:
        Base() {
            cout << "Base class" << endl;
        }
};

class Derived1: public Base
{
    public:
        Derived1() {
            cout << "Derived class 1" << endl;
        }
};

class Derived2: public Base
{
    public:
        Derived2() {
            cout << "Derived class 2" << endl;
        }
};

int main()
{
  Derived1 d1;
  Derived2 d2;
  return 0;
}

输出:

Base class
Derived class 1
Base class
Derived class 2

上面的代码示例有三个类,其中 Derived1 和 Derived2 类继承自公共 Base 类。


C++ 继承中的钻石问题

当我们将层次继承和多重继承结合起来时,就会出现钻石问题。 之所以这样称呼这个问题,是因为类在相互继承的同时形成了菱形。

假设我们有一个场景,有四个类 A、B、C 和 D。

A 类充当基类。 B类被A类继承。 C类也被A类继承。 D 类被 B 类和 C 类继承。

继承中的钻石问题

现在让我们通过代码看看出现的问题。

#include<iostream>
using namespace std;
class A
{
    public:
        A() {
            cout << "Constructor A here!" << endl;
        }
};

class B: public A
{
    public:
           B() {
            cout << "Constructor B here!" << endl;
        }
};

class C: public A
{
    public:
    C() {
        cout << "Constructor C here!" << endl;
    }
};

class D: public B, public C
{
    public:
        D(){
            cout<<"Constructor D here!"<< endl;
        }
};

int main()
{
  D d;
  return 0;
}

输出:

Constructor A here!
Constructor B here!
Constructor A here!
Constructor C here!
Constructor D here!

上面的输出显示,类 A 的构造函数被调用了两次,因为类 D 获得了类 A 的两个副本。一个通过继承类 B,另一个通过继承类 C。

这会产生歧义,在 C++ 中称为钻石问题。

这个问题主要发生在一个类继承多个基类时,这些基类继承自一个公共基类。

不过,这个问题可以使用C++中的virtual关键字来解决。 我们让双父类从同一个基类继承为虚拟类,这样子类就不会获得公共祖父母类的两个副本。

因此,我们在代码示例中创建 B 类和 C 类虚拟类。

让我们借助代码示例来了解此问题的解决方案。

#include<iostream>
using namespace std;
class A
{
    public:
        A() {
            cout << "Constructor A here!" << endl;
        }
};

class B: virtual public A
{
    public:
           B() {
            cout << "Constructor B here!" << endl;
        }
};

class C: virtual public A
{
    public:
    C() {
        cout << "Constructor C here!" << endl;
    }
};

class D: public B, public C
{
    public:
        D(){
            cout<<"Constructor D here!"<< endl;
        }
};

int main()
{
  D d;
  return 0;
}

输出:

Constructor A here!
Constructor B here!
Constructor C here!
Constructor D here!

因此,如上面的输出所示,现在我们只获得了类 A 的构造函数的一份副本。 virtual 关键字告诉编译器,类 B 和类 C 都继承自同一个基类 A; 因此,它应该只被调用一次。


总结

在本文中,我们简要讨论了继承和继承的类型。 然而,我们主要详细讨论了两种类型的继承——多重继承和层次继承,这引起了继承中的钻石问题。

当一个类从多个基类继承,而该基类又从单个基类继承时,就会出现菱形问题。 不过这个问题在C++中使用virtual关键字就解决了。

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

Arduino 中停止循环

发布时间:2024/03/13 浏览次数:444 分类:C++

可以使用 exit(0),无限循环和 Sleep_n0m1 库在 Arduino 中停止循环。

Arduino 复位

发布时间:2024/03/13 浏览次数:315 分类:C++

可以通过使用复位按钮,Softwarereset 库和 Adafruit SleepyDog 库来复位 Arduino。

Arduino 的字符转换为整型

发布时间:2024/03/13 浏览次数:181 分类:C++

可以使用简单的方法 toInt()函数和 Serial.parseInt()函数将 char 转换为 int。

Arduino 串口打印多个变量

发布时间:2024/03/13 浏览次数:381 分类:C++

可以使用 Serial.print()和 Serial.println()函数在串口监视器上显示变量值。

Arduino if 语句

发布时间:2024/03/13 浏览次数:123 分类:C++

可以使用 if 语句检查 Arduino 中的不同条件。

Arduino ICSP

发布时间:2024/03/13 浏览次数:214 分类:C++

ICSP 引脚用于两个 Arduino 之间的通信以及对 Arduino 引导加载程序进行编程。

使用 C++ 编程 Arduino

发布时间:2024/03/13 浏览次数:127 分类:C++

本教程将讨论使用 Arduino IDE 在 C++ 中对 Arduino 进行编程。

Arduino 中的子程序

发布时间:2024/03/13 浏览次数:168 分类:C++

可以通过在 Arduino 中声明函数来处理子程序。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便