2011-03-21 103 views
4
#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

您正在使用类型库,而不是派生。它没有一个函数需要一个double,所以它将转换为int来找到最佳匹配。 – Rob 2011-03-21 00:33:56

回答

8

derived::print不覆盖base中的任何成员函数。它被声明为具有double类型的单个参数,但命名为baseprint两个虚拟成员函数被声明为具有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),它会失败,你需要使用一个使用声明使名称查找过程中可用的那些成员函数。)

0

由于双可以在它看到的第一个定义自动地转换为int(在基类)

参见explicit关键字或this question

1

重载解析发生在编译时。覆盖在运行时发生。

因此,​​的重载分辨率首先发生。这将选择Base::print(int),因为它是唯一一个参数print

在运行时,b指向Derived对象,该对象没有覆盖Base::print(int)。因此,Base::print(int)仍称。