C++中静态和动态绑定的案例

Cases of static and dynamic binding in C++

下面的代码有4个类:Base1,Derived1(派生自Base1),Base2,Derived2(派生自Base2)。两个基数 类 都有整数 data1 和 display_data() 函数。派生的 类 都有整数 data1 和 data2,以及 display_data() 函数。

我在我的代码中尝试了4种情况,在main函数中可以看到。我无法确定其中哪些是静态绑定的情况,哪些是动态的。我需要一些帮助。 我也想知道,这些情况中哪些可以被视为“功能覆盖”。

代码:

#include <iostream>
using namespace std;

class Base1{
protected:
    int data1;

public:
    Base1(int idata1 = 0) {
        data1 = idata1;
    }

    void display_data() {
        cout << "Base1: " << data1 << endl;
    }
};

class Derived1 : public Base1 {
protected:
    int data2;

public:
    Derived1(int idata1 = 0, int idata2 = 0) {
        data1 = idata1;
        data2 = idata2;
    }

    void display_data() {
        cout << "Derived1: " << data1 << ' ' << data2 << endl;
    }
};


class Base2 {
protected:
    int data1;

public:
    Base2(int idata1 = 0) {
        data1 = idata1;
    }

    virtual void display_data() {
        cout << "Base2: " << data1 << endl;
    }
};

class Derived2 : public Base2 {
protected:
    int data2;

public:
    Derived2(int idata1 = 0, int idata2 = 0) {
        data1 = idata1;
        data2 = idata2;
    }

    void display_data() {
        cout << "Derived2: " << data1 << ' ' << data2 << endl;
    }
};

int main()
{
    // case 1
    Derived1 d1(1, 10);
    d1.display_data();

    // case 2
    Base1* d2 = new Derived1(2, 20);
    d2->display_data();

    // case 3
    Derived2 d3(3, 30);
    d3.display_data();

    // case 4
    Base2* d4 = new Derived2(4, 40);
    d4->display_data();

    return 0;
}

输出:

Derived1: 1 10
Base1: 2
Derived2: 3 30
Derived2: 4 40

这是我试图用简单的方式解释它的尝试:)

当对象与基于对象的静态类型(了解其class的类型)的成员函数相关联时,就会发生静态绑定。

当指针或引用与基于对象的动态类型的成员函数相关联时发生动态绑定(了解运行时变量的实例)。

继续阅读之前:动态绑定仅适用于指针或引用以及基类的虚函数 class。

第一次调用是静态绑定(也称为早期绑定),因为调用函数所需的一切都是已知的 在编译时。

    Derived1 d1(1, 10);
    d1.display_data();

你知道d1实例是一个Derived1类型的自动变量然后它会调用 方法 Derived1::display_data().

  • 第一个条件不成立:d1 既不是指针也不是引用。
  • 第二个条件不OK:Derived1::display_data不是虚

第二次调用

    Base1* d2 = new Derived1(2, 20);
    d2->display_data();

我们看到变量d2的声明类型是Base1但实例是Derived1(它 是正确的,因为继承因此 Derived1Base1 class)。但你还不知道 如果它将调用的 display_data 方法是来自 Base1::display_data 的方法或来自 Base1::display_data 的方法 Derived1::display_data.

  • 第一个条件是可以的,因为我们有d2类型的指针Base1*
  • 第二个条件不OK,因为Base1::display_data不是虚拟的。因此它仍然是 一个静态绑定那么将被调用的函数是具有声明类型的函数,因此 代码将调用 Base1::display_data

第三次调用

    // case 3
    Derived2 d3(3, 30);
    d3.display_data();

这将导致静态绑定,然后调用 Derived3::display_data

  • 第一个条件不成立:d3 既不是指针也不是引用。
  • 第二个条件OK:Derived2::display_data为虚

第四次通话

    Base2* d4 = new Derived2(4, 40);
    d4->display_data();

这次是动态绑定

  • 第一个条件OK:d4是一个指针。
  • 第二个条件OK:Derived2::display_data是虚拟的。 因此,它不会从声明的类型 base2 调用方法,而是调用方法 来自运行时声明的实例 Derived2::display_data