Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C+中静态和动态绑定的情况+;_C++_Oop_Polymorphism_Dynamic Binding_Static Binding - Fatal编程技术网

C++ C+中静态和动态绑定的情况+;

C++ C+中静态和动态绑定的情况+;,c++,oop,polymorphism,dynamic-binding,static-binding,C++,Oop,Polymorphism,Dynamic Binding,Static Binding,以下代码有4个类:Base1、Derived1(派生自Base1)、Base2、Derived2(派生自Base2)。这两个基类都有整数data1和display_data()函数。这两个派生类都有整数data1和data2,并显示_data()函数 我在我的代码中尝试了4个案例,可以在main函数中看到。我无法确定哪一个是静态绑定,哪一个是动态绑定。我需要一些帮助。 我还想知道,在这些情况中,哪些可以被视为“功能重写” 代码: #include <iostream> using n

以下代码有4个类:Base1、Derived1(派生自Base1)、Base2、Derived2(派生自Base2)。这两个基类都有整数data1和display_data()函数。这两个派生类都有整数data1和data2,并显示_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

以下是我试图用一种简单的方式来解释它:)

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

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

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

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

衍生1 d1(1,10);
d1.显示_数据();
您知道
d1
实例是类型为
Derived1
的自动变量,然后它将调用 方法
Derived1::display\u data()

  • 第一个条件不正常:d1既不是指针,也不是引用
  • 第二个条件不正常:
    Derived1::display\u data
    不是虚拟的
第二个电话

Base1*d2=新衍生的1(2,20);
d2->显示_数据();
我们看到变量
d2
的声明类型是
Base1
,但实例是
Derived1
(它是 由于继承而正确,因此
Derived1
Base1
类)。但你现在还不知道 如果它将调用的
display\u data
方法是来自
Base1::display\u data
的方法,则
Derived1::显示数据

  • 第一个条件是OK的,因为我们有类型为pointer
    Base1*
    d2
  • 第二个条件不正常,因为
    Base1::display\u data
    不是虚拟的。因此它仍然是 静态绑定则将被调用的函数是具有声明类型的函数,因此 代码将调用
    Base1::显示\u数据
第三个电话

//案例3
衍生2 d3(3,30);
d3.显示_数据();
这将导致静态绑定,然后调用
Derived3::display\u data

  • 第一个条件不正常:d3既不是指针,也不是引用
  • 第二个条件是确定的:
    Derived2::display\u data
    是虚拟的
第四个电话

Base2*d4=新衍生的2(4,40);
d4->显示_数据();
这次是一个动态绑定

  • 第一个条件是OK:d4是指针
  • 第二个条件是确定的:
    Derived2::display\u data
    是虚拟的。 因此,它将调用该方法,而不是从声明的类型
    base2
    调用该方法 从运行时声明的实例派生2::显示\u数据

这里的关键是函数说明符。当成员函数不是
virtual
时,使用的版本在编译时根据调用函数的对象的类型确定——因此在案例2中,您会看到调用
Base1::display\u data
,因为它是从
Base1*
指针调用的。当函数为
virtual
时,使用的版本将在运行时根据对象的实际最派生类型确定,如案例4所示。当您阅读“virtual”时,请考虑“动态绑定和可重写”。是否有实用的方法来确定代码的某个部分使用的是静态绑定还是动态绑定?类似于ide功能或一些打印语句,以便能够用于出现的任何其他情况。还是我们必须按照你解释的方式来理解?此外,您还可以澄清是否所有这些情况都被视为“方法重写”吗?我可能会对它的定义感到困惑,因为网上有多种可用的资源。这与它是虚拟的有关吗?谢谢你这么详细的回答。这澄清了静态和动态绑定的概念。:)实用的方法是找到@molbdnilo告诉我们的关键字
virtual
。您可以阅读为什么
析构函数
应该是虚拟的或者不是虚拟的,并更好地理解为什么方法也应该是虚拟的。实际上,动态绑定是通过虚拟方法的继承(覆盖)来利用的。方法溢出是指在派生类方法中重新定义基类方法,但更改其定义(正是您对派生类所做的)。你可能有一些简明的文学作品