虚函数查找的规则是啥?
Posted
技术标签:
【中文标题】虚函数查找的规则是啥?【英文标题】:What are the rules for virtual function lookup?虚函数查找的规则是什么? 【发布时间】:2011-03-21 00:29:18 【问题描述】:#include <iostream>
class base
public:
virtual void print (int a)
std::cout << "a: " << a << " base\n";
virtual void print (int a, int b)
std::cout << "base\n";
;
class derived : public base
public:
virtual void print (double d)
std::cout << "derived\n";
;
int main ()
int i = 10;
double d = 10000.0;
base *b = new derived ();
b->print (i, i);
b->print (d);
return 0;
这个函数的输出是:
base
a: 10000 base
为什么b->print (d)
不调用派生类实现和
对'd'
执行静态转换以提供与基类的匹配
实施?
在查找虚函数时这里应用了什么规则?
【问题讨论】:
您使用的是基础类型,而不是派生类型。它没有接受双精度的函数,因此它强制转换为 int 以找到最佳匹配。 【参考方案1】:derived::print
不会覆盖base
中的任何成员函数。它被声明为具有double
类型的单个参数,但base
中名为print
的两个虚成员函数被声明为具有int
类型的一个和两个参数。
当您使用b->print(d)
时,在重载解析期间仅考虑base
中的成员函数,因此仅考虑void base::print(int)
和void base::print(int, int)
。找不到void derived::print(double)
,因为编译器不知道b
指向derived
对象。
如果derived
要覆盖base
中声明为虚拟成员函数的两个print
函数之一,则将在运行时调用该覆盖。
(在一些相关的注释中,derived::print
隐藏了两个base::print
成员函数,因此如果您尝试使用基类print
函数之一,例如derived().print(1, 1)
,它将失败。您需要使用 using 声明来使这些成员函数在名称查找期间可用。)
【讨论】:
【参考方案2】:重载解析发生在编译时。覆盖发生在运行时。
因此,b->print(d);
的重载决议首先发生。这选择了Base::print(int)
,因为它是唯一的一个参数print
。
在运行时,b
指向一个没有覆盖 Base::print(int)
的 Derived
对象。因此,Base::print(int)
仍然被调用。
【讨论】:
【参考方案3】:因为 double 可以在它看到的第一个定义中(在基类中)自动转换为 int
见explicit
关键字或this question
【讨论】:
以上是关于虚函数查找的规则是啥?的主要内容,如果未能解决你的问题,请参考以下文章