【问题标题】:Custom cast not applied to references of derived class自定义转换不适用于派生类的引用
【发布时间】:2016-08-03 19:33:44
【问题描述】:

在转换引用时,编译器似乎试图将 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"
}

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

【问题讨论】:

  • 你会注意到你的基类是 private 故意的,是吗?
  • @WhozCraig 这是有意的,因此我们需要演员阵容。不过它确实适用于指针。
  • 好吧,前者(引用)无论如何都不会被调用,你的编译器应该已经警告过你:clang,例如:“转换函数将'Derived'转换为其基类'Base ' 永远不会被使用”。
  • 我试图理解为什么可以使用指针而不是引用来转换它。

标签: c++ templates inheritance casting reference


【解决方案1】:

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

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

确实clang给出了警告:

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

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

如果你真的想使用转换运算符进行引用,你必须显式调用它:

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

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

【讨论】:

  • 或者使用组合来重用,而不是继承。
猜你喜欢
  • 2012-01-04
  • 2012-04-30
  • 2018-09-14
  • 2012-09-01
  • 2012-09-11
  • 2021-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多