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

ale*_*lex 2 c++ inheritance templates casting reference

在转换引用时,似乎编译器尝试将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"
}
Run Code Online (Sandbox Code Playgroud)

为什么不能像这样使用自定义转换?是否有可能实现预期的行为(使用引用"向上转换"到不可到达的基础)?

Ant*_*vin 5

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

转换函数从不用于将(可能是cv限定的)对象转换为(可能是cv限定的)相同的对象类型(或对它的引用),转换为该类型的(可能是cv限定的)基类(或引用它)或(可能是cv-qualified)void.

确实clang发出警告:

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

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

如果您确实想要使用转换运算符作为引用,则必须显式调用它:

std::cout << dRef.operator Base&().fn() << std::endl;
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,你可能想要为它创建一个普通的成员函数,或者说实话,只需将继承公之于众.

  • 或者使用组合来重用,而不是继承. (2认同)