运算符const Base&()是否应该用于不可访问的基类?

时间:2015-02-06 17:15:57

标签: c++ c++11 c++14

我想有一个类允许访问它的基本情况的const接口,但不是。特别是:

class B
{};

class A : private class B
{
public:
  operator const B&() { return *this; }
};

int main()
{
  A a;
  const B& b = a; // Should this line be an error?
}

g ++给出了一个无法访问的基类错误。那些语言专家认为这个错误在C ++ 11 / C ++ 14中是正确的吗?

是的,我知道我可以(而且会)这样做:

int main()
{
  A a;
  const B& b = a.operator const B&();
}

有关此构造的另一种方法的任何建议吗?

3 个答案:

答案 0 :(得分:5)

[dcl.init.ref] / 5:

  

对类型“ cv1 T1”的引用由表达式初始化   输入“ cv2 T2”如下:

     
      
  • 如果引用是左值引用和初始值设定项   表达

         
        
    • 是左值(但不是位字段),“ cv1 T1”与“ cv2 {{1}”引用兼容},“或
    •   
    • 有一个类类型(即,T2是一个类类型),其中T2T1 没有参考相关,[..]
    •   
         

    然后将引用绑定到初始化表达式lvalue中   第一种情况和转化的左值结果   第二种情况(或者,在任何一种情况下,到适当的基类   对象的子对象)。

  •   

转换功能将在第二个要点中介绍。但是,T2B的引用相关(并且与其相容),即使它是私有基类,因此第一个项目符号适用。现在[dcl.init.ref] / 4将此场景定义为格式错误:

  

指定类型“ cv1 A”和“ cv1 T1”,“ cv1 {{1} “是的   与参考相关的到“ cv1 T2”如果T1T2的类型相同,   或T1T2的基类。如果T1是参考,则“ cv1 T2参考兼容与“ cv2 T1”与T2 cv1 相关                         与 cv2 相同的cv资格,或更高的cv资格。 在所有与参考相关的情况下                            或两种类型的参考兼容关系用于建立参考绑定的有效性,和                           T1T2的基类,如果T1T2的无法访问的基类,那么需要这种绑定的程序就是格式不正确的

这样的引用绑定因此总是会失败,无论可用的任何转换函数如何。引用绑定不能与私有继承一起使用。

您的显式调用是此问题的解决方案,但不再需要转换运算符:只需定义一个返回T1 - 引用的getter。 E.g。

T2

答案 1 :(得分:3)

const B& b = a;

不会调用A::operator const B&()。从C ++ 03天开始就存在这种行为 这是一个简单的向上转换,它从派生类型到基本类型发生。此向上转换会引发编译器错误,因为基类(class B)由全局范围内的派生(class A)私有继承。

如果BA之间没有这种继承关系,那么所提到的operator const B&()肯定会根据您的期望进行实例化。

答案 2 :(得分:2)

错误是正确的。只有在类型与引用无关时,才会考虑隐式转换(在这种情况下,通过运算符)。继承关系意味着它们是,因此引用将直接绑定而不进行转换,但由于私有继承而失败。

除非你有充分的继承理由,否则你可能会使A成员而不是基类。在这种情况下,返回对该成员的引用的转换运算符将执行您想要的操作。

如果确实需要继承,那么适当命名的函数可能比要求显式的操作符调用更好。