请看示例 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
中,唯一可见的print
是IA::print
。 所以IA::run
打电话给IA::print
.
在A::run
中,你可以看到IA::print
和A::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 条(。