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

时间:2016-04-12 23:38:03

标签: c++ templates inheritance 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"
}

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

1 个答案:

答案 0 :(得分:5)

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

  

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

确实clang发出警告:

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;

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