自定义强制转换未应用于派生类的引用

Custom cast not applied to references of derived class

本文关键字:派生 引用 应用于 转换 自定义      更新时间:2023-10-16

在强制转换引用时,编译器似乎试图将Derived类转换为其Base,并且根本不使用自定义强制转换。不过,这与指针完美配合。

示例:

#include <iostream>
class Base {
public:
    int fn() {
        return 42;
    }
};
class Derived : private Base {
public:
    operator Base&() {
        return *dynamic_cast<Base*>(this);
    }
    operator Base*() {
        return dynamic_cast<Base*>(this);
    }
};
int main() {
    Derived d;
    Derived &dRef = d;
    std::cout<<static_cast<Base&>(dRef).fn()<<std::endl;    // <-- error: non-reachable base >>Base<< of >>Derived<<
    std::cout<<static_cast<Base*>(d)->fn()<<std::endl;      // OK -> "42"
}

为什么不能像这样使用自定义铸造?是否有可能实现预期行为("向上投射"到具有引用的不可访问的基础)?

[class.conv.fct]/1读取(强调矿):

转换函数从不用于将(可能是cv限定的)对象转换为(可能是cv限定的)相同的对象类型(或对它的引用),到该类型的(可能是cv限定的)基类(或对的引用it),或作废(可能是cv合格)。

叮当确实发出了警告:

warning: conversion function converting 'Derived' to its base class 'Base' will never be used
operator Base&() {
^

指针没有这样的限制,所以static_cast<Base*>(d)可以工作并调用自定义转换运算符。

如果你真的想使用转换运算符作为引用,你必须明确地调用它:

std::cout << dRef.operator Base&().fn() << std::endl;

但在这种情况下,您可能只想为此创建一个常规成员函数,或者诚实地公开继承。