【问题标题】: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-&gt;print (d) 不调用派生类实现和 对'd' 执行静态转换以提供与基类的匹配 实施?
  • 在查找虚函数时这里应用了什么规则?

【问题讨论】:

  • 您使用的是基础类型,而不是派生类型。它没有接受双精度的函数,因此它强制转换为 int 以找到最佳匹配。

标签: c++ overriding virtual-functions


【解决方案1】:

derived::print 不会覆盖base 中的任何成员函数。它被声明为具有double 类型的单个参数,但base 中名为print 的两个虚成员函数被声明为具有int 类型的一个和两个参数。

当您使用b-&gt;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-&gt;print(d); 的重载决议首先发生。这选择了Base::print(int),因为它是唯一的一个参数print

    在运行时,b 指向一个没有覆盖 Base::print(int)Derived 对象。因此,Base::print(int) 仍然被调用。

    【讨论】:

      【解决方案3】:

      因为 double 可以在它看到的第一个定义中(在基类中)自动转换为 int

      explicit关键字或this question

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-10-26
        • 2018-01-26
        • 2010-09-12
        • 2017-11-03
        • 1970-01-01
        • 2016-11-01
        相关资源
        最近更新 更多