虚函数查找的规则是什么?
#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
- Why
b->print (d)
don't invoke the导出类实现并且 对'd'
执行静态转换以提供与基类的匹配 执行 ? - 在虚函数查找期间应用什么规则?
#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;
}
The output of this function is:
base
a: 10000 base
- Why
b->print (d)
don't invoke the derived class implementation and
performs static cast on'd'
to provide a match with base class
implementation ? - What rule is applied here during virtual function lookup ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
衍生::打印
不会覆盖base
中的任何成员函数。它被声明为具有double
类型的单个参数,但base
中名为print
的两个虚拟成员函数被声明为具有一个和两个参数int
类型。当您使用
b->print(d)
时,在重载解析期间仅考虑base
中的成员函数,因此仅void base::print(int)考虑
和void base::print(int, int)
。无法找到void衍生::print(double)
,因为编译器不知道b
指向衍生
对象。如果
衍生
要重写在base
中声明为虚拟成员函数的两个print
函数之一,则该重写将在运行时调用。(在某种程度上相关的说明中,派生::print 隐藏了两个基类::print 成员函数,因此如果您尝试使用基类之一
print
函数,例如衍生().print(1, 1)
,它会失败。您需要使用 using 声明来使这些成员函数在名称查找期间可用。 )derived::print
does not override any member function inbase
. It is declared as having a single parameter of typedouble
but the two virtual member functions namedprint
inbase
are declared as having one and two parameters of typeint
.When you use
b->print(d)
, only member functions inbase
are considered during overload resolution, so onlyvoid base::print(int)
andvoid base::print(int, int)
are considered.void derived::print(double)
can't be found because the compiler has no idea thatb
points to aderived
object.If
derived
were to override one of the twoprint
functions declared as virtual member functions inbase
, then that override would be called at runtime.(On a somewhat related note,
derived::print
hides the twobase::print
member functions, so if you were to try to use one of the base classprint
functions, e.g.,derived().print(1, 1)
, it would fail. You would need to use a using declaration to make those member functions available during name lookup.)重载解析发生在编译时。覆盖发生在运行时。
因此,
b->print(d);
的重载决策首先发生。这会选择Base::print(int)
,因为它是唯一的一个参数print
。在运行时,
b
指向一个Derived
对象,该对象没有覆盖Base::print(int)
。因此,Base::print(int)
仍然被调用。Overload resolution happens at compile time. Overrides happen at run time.
Therefore, the overload resolution of
b->print(d);
happens first. This selectsBase::print(int)
because it's the only one-argumentprint
.At runtime,
b
points to aDerived
object that has no override forBase::print(int)
. Therefore,Base::print(int)
is still called.因为 double 可以在它看到的第一个定义(在基类中)中自动转换为 int
请参阅
explicit
关键字或 这个问题Because double can be automatically converted to an int in the first definition it sees (in the base class)
See
explicit
keyword or this question