下面的代码有4个类:Base1、Derived1(派生自Base1)、Base2、Derived2(派生自Base2)。两个基本类都有整数data1和display_data()函数。这两个派生类都有整数data1和data2,以及display_data()函数。
我在我的代码中尝试了4个案例,可以在主函数中看到。我不知道哪一个是静态绑定,哪一个是动态绑定。我需要一些帮助。我还想知道,这些情况中哪些可以认为是“函数重写”。
代码:
#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
下面是我试图用一种简单的方式来解释的:)
当对象与基于对象的静态类型(理解其类的类型)的成员函数关联时,就会发生静态绑定。
当指针或引用与基于对象的动态类型(在运行时理解变量的实例)的成员函数相关联时,就会发生动态绑定。
在阅读之前:动态绑定仅适用于指针或引用以及基类的虚函数。
第一个调用是静态绑定(也称为早期绑定),因为调用函数所需的一切在编译时都已知。
Derived1 d1(1, 10);
d1.display_data();
您知道d1
实例是derived1
类型的自动变量,然后它将调用derived1::display_data()
方法。
derived1::display_data
不是虚拟的。对于第二个呼叫
Base1* d2 = new Derived1(2, 20);
d2->display_data();
我们看到变量d2
的声明类型是base1
的,但实例是derived1
的(这是正确的,因为继承,因此derived1
是一个base1
类)。但您还不知道它将调用的display_data
方法是来自base1::display_data
的方法还是来自derived1::display_data
的方法。
base1*
的D2
。base1::display_data
不是虚拟的。因此它仍然是一个静态绑定,那么将要调用的函数就是具有声明类型的函数,因此代码将调用base1::display_data
第三次呼叫
// case 3
Derived2 d3(3, 30);
d3.display_data();
这将导致静态绑定,然后调用derived3::display_data
derived2::display_data
是虚拟的。对于第四次呼叫
Base2* d4 = new Derived2(4, 40);
d4->display_data();
这一次是动态绑定。
derived2::display_data
是虚拟的。因此,它不是从声明的类型base2
调用方法,而是在运行时derived2::display_data