我想有一个类允许访问它的基本情况的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&();
}
有关此构造的另一种方法的任何建议吗?
答案 0 :(得分:5)
[dcl.init.ref] / 5:
对类型“ cv1
T1
”的引用由表达式初始化 输入“ cv2T2
”如下:
如果引用是左值引用和初始值设定项 表达
- 是左值(但不是位字段),“ cv1
T1
”与“ cv2 {{1}”引用兼容},“或- 有一个类类型(即,
T2
是一个类类型),其中T2
与T1
没有参考相关,[..]然后将引用绑定到初始化表达式lvalue中 第一种情况和转化的左值结果 第二种情况(或者,在任何一种情况下,到适当的基类 对象的子对象)。
转换功能将在第二个要点中介绍。但是,T2
与B
的引用相关(并且与其相容),即使它是私有基类,因此第一个项目符号适用。现在[dcl.init.ref] / 4将此场景定义为格式错误:
指定类型“ cv1
A
”和“ cv1T1
”,“ cv1 {{1} “是的 与参考相关的到“ cv1T2
”如果T1
与T2
的类型相同, 或T1
是T2
的基类。如果T1
是参考,则“ cv1T2
”参考兼容与“ cv2T1
”与T2
和 cv1 相关 与 cv2 相同的cv资格,或更高的cv资格。 在所有与参考相关的情况下 或两种类型的参考兼容关系用于建立参考绑定的有效性,和T1
是T2
的基类,如果T1
是T2
的无法访问的基类,那么需要这种绑定的程序就是格式不正确的1}强>
这样的引用绑定因此总是会失败,无论可用的任何转换函数如何。引用绑定不能与私有继承一起使用。
您的显式调用是此问题的解决方案,但不再需要转换运算符:只需定义一个返回T1
- 引用的getter。 E.g。
T2
答案 1 :(得分:3)
const B& b = a;
不会调用A::operator const B&()
。从C ++ 03天开始就存在这种行为
这是一个简单的向上转换,它从派生类型到基本类型发生。此向上转换会引发编译器错误,因为基类(class B
)由全局范围内的派生(class A
)私有继承。
如果B
和A
之间没有这种继承关系,那么所提到的operator const B&()
肯定会根据您的期望进行实例化。
答案 2 :(得分:2)
错误是正确的。只有在类型与引用无关时,才会考虑隐式转换(在这种情况下,通过运算符)。继承关系意味着它们是,因此引用将直接绑定而不进行转换,但由于私有继承而失败。
除非你有充分的继承理由,否则你可能会使A
成员而不是基类。在这种情况下,返回对该成员的引用的转换运算符将执行您想要的操作。
如果确实需要继承,那么适当命名的函数可能比要求显式的操作符调用更好。