基址指针到 void 的转换为何优于派生指针到 void 的转换

mad*_*ada 8 c++ class overload-resolution

[over.ics.rank]/4

  • [..]
  • (4.3) 如果类 B 直接或间接从类 A 派生,则 B* 到 A* 的转换优于 B* 到 void* 的转换,并且 A* 到 void* 的转换优于 B* 到 void 的转换*。

所以如果我有:

struct A {};
struct M : A {};
struct B : M {};

void f(A*);
void f(void*);

int main()
{
   B *bptr = new B();
   f(bptr);
}
Run Code Online (Sandbox Code Playgroud)

该调用f(bptr)更喜欢重载f(A*)而不是f(void*).

但在第二种情况下:A* 到 void* 的转换比 B* 到 void* 的转换要好。这种转变如何发生?你能给我一个触发这个案例的例子吗?


由于某些原因,我找不到应用该案例的案例或示例。这看起来就像是在比较两个不相关的事物。但我在子弹4.4中遇到更多。

您可以从cppreference para 4中检查整个内容:

  1. 如果 Mid 是(直接或间接)从 Base 派生的,并且 Derived 是(直接或间接)从 Mid 派生的
  • a) Derived* 到 Mid* 优于 Derived* 到 Base*
  • b) 导出到 Mid& 或 Mid&& 优于导出到 Base& 或 Base&&
  • c) Base::* 到 Mid::* 优于 Base::* 到 Derived::*
  • d) 导出到 Mid 优于导出到 Base
  • e) Mid* 到 Base* 优于 Derived* 到 Base*
  • f) Mid to Base&或Base&&优于Derived to Base&或Base&&
  • g) Mid::* 到 Derived::* 优于 Base::* 到 Derived::*
  • h) 中值到基础优于衍生到基础

use*_*522 5

必须比较不同可能的源类型(A*B*inA* -> void*B* -> void*)的情况只能发生在通过用户定义的转换进行初始化的重载解析上下文中,而不是在函数调用的重载解析上下文中。另请参阅[over.ics.rank]/4 末尾的注释

以下是引用短语相关的示例:

struct A {};
struct B : A {};

struct C {
    operator A*();
    operator B*();
};

int main() {
    void* x = C{};
}
Run Code Online (Sandbox Code Playgroud)

这里x通过根据[over.match.conv]选择的转换函数进行初始化(请参阅[dcl.init.general]/16.7)。考虑从可通过标准转换序列转换C为的任何类型转换的所有转换运算符。void*

然后根据转换函数后面的标准转换序列中哪个更好来选择最佳转换函数(参见[over.match.best.general]/2.2)。

你引用的这句话告诉我们,这A* -> void*比……更好B* -> void*。所以这里将使用的初始化转换函数xoperator A*()