为什么派生类的实例从基类调用方法?

  • 本文关键字:基类 调用 方法 实例 派生 c++
  • 更新时间 :
  • 英文 :


请看示例 1 和示例 2。
示例 1 与示例 2 的区别仅在于重写的方法 run(( 来自 ** 类 IA **
问题写在末尾。

示例 1:

#include <iostream>
class IA {
public:
void run() {
print();
}
void print() {
std::cout << "IA::print() n";
}
};
class A : public IA {
public:
void print() {
std::cout << "A:: n";
}
};
int main() {
A a1;
a1.run();
A * ptr = new A;
ptr->run();
}

此代码打印:

IA::p rint((
IA::p rint((

示例 2:

#include <iostream>
class IA {
public:
void run() {
print();
}
void print() {
std::cout << "IA::print() n";
}
};
class A : public IA {
public:
void run() {
print();
}
void print() {
std::cout << "A:: n";
}
};
int main() {
A a1;
a1.run();
A * ptr = new A;
ptr->run();
}

此代码打印:

一个::
一个::

为什么这样打印?有什么区别?

谢谢。

你选择不print虚拟的。 这意味着不会发生动态调度。 在调用该方法的任何时候,本地类型信息都用于确定调用哪一个方法。

void run() {
print();
}

所以当你调用一个非虚拟print时,无论从哪里看到run的本地print函数都会被调用。

IA::run中,唯一可见的printIA::print。 所以IA::run打电话给IA::print.

A::run中,你可以看到IA::printA::print;但第二个隐藏了第一个。 所以A::print被称为。

对象的实际动态类型是什么并不重要,因为您没有要求虚拟调度。 您要求使用本地静态类型信息选取函数。


您可以要求虚拟派单:

class IA {
public:
void run() {
print();
}
virtual void print() {
std::cout << "IA::print() n";
}
};

我将关键字virtual添加到print. 现在第一个版本将调用A::版本的print.

某些语言使所有方法都隐式虚拟。 C++不会,因为虚拟方法有一些运行时开销,C++尽量不让你为不使用的东西付费。

在第一个程序中,成员函数运行是基类的函数。在函数中,足尖this的静态类型为IA。根据this的静态类型在IA类中搜索函数打印。

在第二个程序中,类 A 运行和打印这两个函数。它们隐藏了类 IA 的相应功能。所以他们被称为

从C++标准(13.2 成员名称查找(

1 成员名称查找确定名称的含义(id-表达式( 在类范围 (6.3.7( 中。名称查找可能会导致歧义,在 哪种情况程序格式不正确。对于 id 表达式,名称 查找从此类范围开始;对于限定 ID,名称 查找从嵌套名称说明符的范围开始。名称查找 在访问控制之前进行(6.4,第 14 条(。

最新更新