虚函数查找的规则是什么?

5
#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' 进行静态转换以与基类实现匹配?
  • 在虚函数查找期间应用了哪个规则?

3
你正在处理基础类型,而不是派生类型。它没有接受双精度数值的函数,所以将其转换成整型来找到最佳匹配。 - Rob
3个回答

8
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声明来使这些成员函数在名称查找期间可用。)

1

重载决议发生在编译时。覆盖发生在运行时。

因此,b->print(d); 的重载决议首先发生。这选择了 Base::print(int),因为它是唯一的单参数 print

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


0

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

请参见 explicit 关键字或 此问题


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接