C++ 操作员是否应保持基本和;()是否用于不可访问的基类?

C++ 操作员是否应保持基本和;()是否用于不可访问的基类?,c++,c++11,c++14,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++给出了一个不可访问的基类错误。你们的语言专家认为这个错误

我希望有一个类,它允许访问它的基本情况的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&();
}
对这种构造的另一种方法有什么建议吗

[dcl.init.ref]/5:

对类型“cv1
T1
”的引用由以下表达式初始化 键入“cv2
T2
”,如下所示:

  • 如果引用是左值引用且初始值设定项 表情

    • 是左值(但不是位字段),“cv1
      T1
      ”是与“cv2
      T2
      ”兼容的引用,或
    • 有一个类类型(即,
      T2
      是一个类类型),其中
      T1
      T2无关,[…]
    然后将引用绑定到中的初始值设定项表达式左值 第一种情况是在 第二种情况(或者,在任何一种情况下,都适用于适当的基类) 对象的子对象)

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

给定类型“cv1
T1
”和“cv1
T2
”,“cv1
T1
”是 如果
T1
T2
类型相同,则与“cv1
T2
相关的参考, 或者
T1
T2
的基类。如果
T1
参考与
T2
和cv1相关,则“cv1
T1
”参考与“cv2
T2
”兼容 与cv2相同或大于cv2在引用相关的所有情况下 或使用两种类型的引用兼容关系来确定引用绑定的有效性,以及
T1
T2
的基类,如果
T1
T2
的不可访问的[…]基类,则需要这种绑定的程序格式不正确

因此,无论任何可用的转换函数如何,此类引用绑定都将始终失败。引用绑定不能与私有继承一起使用

显式调用就是这个问题的解决方案,尽管不再需要转换运算符:只需定义一个返回
const
-reference的getter即可。例如

const B& b = a.getB();
不调用
A::operator const B&()
。此行为自C++03天起就存在。
这是一个简单的向上转换,从派生类型到基类型。此向上转换引发编译器错误,因为基(
类B
)由全局范围内的派生(
类A
)私有继承


如果
B
A
之间没有这样的继承关系,那么所提到的
操作符const B&(()
肯定会按照您的期望实例化。

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

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


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

您已经有了说明这是错误的答案,但是,想想如果不是错误会发生什么:这意味着
const B&B=a
的行为完全不同,这取决于它是否出现在
a
朋友中。为什么不只是组合而不是私有继承呢?
const B& b = a;