C++ 虚拟函数查找的规则是什么? 为什么b->print(d)不调用派生类实现和 对'd'执行静态强制转换,以提供与基类的匹配 实施 在虚拟函数查找期间,此处应用了什么规则

C++ 虚拟函数查找的规则是什么? 为什么b->print(d)不调用派生类实现和 对'd'执行静态强制转换,以提供与基类的匹配 实施 在虚拟函数查找期间,此处应用了什么规则,c++,overriding,virtual-functions,C++,Overriding,Virtual Functions,派生::打印不会覆盖基中的任何成员函数。它被声明为具有类型为double的单个参数,但base中名为print的两个虚拟成员函数被声明为具有类型为int的一个和两个参数 当您使用b->print(d)时,重载解析期间只考虑base中的成员函数,因此只考虑void base::print(int)和void base::print(int,int)无效派生::打印(双精度),因为编译器不知道b指向派生的对象 如果derived要覆盖print中声明为base中的虚拟成员函数的两个函数之一,则会在运

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

当您使用
b->print(d)
时,重载解析期间只考虑
base
中的成员函数,因此只考虑
void base::print(int)
void base::print(int,int)
<无法找到代码>无效派生::打印(双精度),因为编译器不知道
b
指向
派生的
对象

如果
derived
要覆盖
print
中声明为
base
中的虚拟成员函数的两个
函数之一,则会在运行时调用该覆盖


(在某种程度上相关的注释中,
derived::print
隐藏了两个
base::print
成员函数,因此如果您试图使用其中一个基类
print
函数,例如,
derived().print(1,1)
,它将失败。您需要使用using声明使这些成员函数在名称查找期间可用。)

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


请参阅
explicit
关键字或重载解析在编译时发生。重写发生在运行时

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


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

您使用的是类型Base,而不是派生的。它没有一个需要双精度的函数,所以它将转换为int以找到最佳匹配。
#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