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

问题描述

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

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

代码

var objPres = objPresSet.Open(
                path,MsoTriState.msoFalse /* ConfirmConversions */,MsoTriState.msoTrue,MsoTriState.msoFalse);

输出

#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 d1(1,10);
    d1.display_data();

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

  • 第一个条件不合适:d1 既不是指针也不是引用。
  • 第二个条件不合适:Derived1::display_data 不是虚拟的。

第二次通话

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

我们看到变量d2的声明类型是Base1,而实例是Derived1(它 由于继承是正确的,因此 Derived1 是一个 Base1 类)。但你还不知道在 如果它将调用的 display_data 方法是来自 Base1::display_data 的方法 o 来自 Derived1::display_data

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

第三次调用

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

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

  • 第一个条件不合适:d3 既不是指针也不是引用。
  • 第二个条件是可以的:Derived2::display_data 是虚拟的。

第四次调用

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

这次是动态绑定。

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