You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++重载决议:基类指针转void*更优规则的触发场景示例

规则触发场景说明

A*到void*的转换优于B*到void*这条规则的核心作用,是在两个同等级隐式转换序列都需要最终转换为void*时,基于指针所属类型的继承关系给出优先级判断。纯标准转换场景下很难触发这条规则——因为当形参直接是void*时,编译器会直接选择最短转换路径(派生类指针直接转void*),不会生成“派生类指针→基类指针→void*”的冗余路径,自然不会出现两个待比较的void*转换序列。

这条规则最典型的触发场景是用户定义转换序列的标准转换段比较:当类同时定义了到基类指针、派生类指针的转换运算符,且调用目标形参为void*时,两条转换路径都属于可行序列,此时就需要用这条规则判定优先级。

可复现的代码示例

#include <iostream>
struct A {};
struct B : A {};

struct C {
    operator A*() {
        std::cout << "调用C::operator A*()\n";
        return nullptr;
    }
    operator B*() {
        std::cout << "调用C::operator B*()\n";
        return nullptr;
    }
};

void f(void*) {
    std::cout << "调用f(void*)\n";
}

int main() {
    C c;
    f(c);
}

规则匹配逻辑说明

调用f(c)时,编译器会生成两个可行的隐式转换序列:

  • 序列1:对c调用operator A*()得到A*类型临时值,再通过标准指针转换A*→void*匹配f的形参
  • 序列2:对c调用operator B*()得到B*类型临时值,再通过标准指针转换B*→void*匹配f的形参

两个序列同属用户定义转换等级,用户定义转换步骤本身没有优先级差异,因此需要比较用户定义转换之后的标准转换段优劣。此时恰好匹配规则的适用条件:A是B的基类,A*→void*的转换优先级高于B*→void*,因此序列1更优,编译器会选择调用operator A*()完成转换,不会产生二义性错误。

程序运行输出为:

调用C::operator A*()
调用f(void*)

如果删除这条规则,上述代码会因为两个转换序列优先级相同直接报编译期二义性错误。


补充:基类层级相关的隐式转换序列排名规则

若Mid直接或间接派生自Base,且Derived直接或间接派生自Mid:

  • Derived到Mid的转换优于Derived到Base的转换
  • Derived到Mid&或Mid&&的转换优于Derived到Base&或Base&&的转换
  • Base::*到Mid::*的转换优于Base::*到Derived::*的转换
  • Derived到Mid的转换优于Derived到Base的转换
  • Mid到Base的转换优于Derived到Base的转换
  • Mid到Base&或Base&&的转换优于Derived到Base&或Base&&的转换
  • Mid::*到Derived::*的转换优于Base::*到Derived::*的转换
  • Mid到Base的转换优于Derived到Base的转换

内容的提问来源于stack exchange,提问作者mada

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 15:00:49