2015-02-06 22 views
5

我想有一个类,它允许访问它的基本情况的const接口,但不是。特别是:应该将运算符const Base&()用于不可访问的基类吗?

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

你已经有答案说明这是一个错误,但也想想看会发生什么,如果它不是一个错误:它将意味着'const B&b = a;'具有完全不同的行为,取决于它是否出现在'A'的'朋友'。 – hvd 2015-02-06 17:42:38

+0

为什么不只是组合而不是私有继承? – 2015-02-06 17:49:12

回答

5

[dcl.init.ref]/5:

A reference to type “cv1T1 ” is initialized by an expression of type “cv2T2 ” as follows:

  • If the reference is an lvalue reference and the initializer expression

    • is an lvalue (but is not a bit-field), and “cv1T1 ” is reference-compatible with “cv2T2 ,” or
    • has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, [..]

    then the reference is bound to the initializer expression lvalue in the first case and to the lvalue result of the conversion in the second case (or, in either case, to the appropriate base class subobject of the object).

转换函数将被覆盖在所述第二项目符号点。然而,即使它是私有基类,B与(并与之兼容)A也是引用相关的,因此第一个要点适用。现在[dcl.init.ref/4定义这种情况下是非法的构造:

Given types “cv1T1 ” and “cv1T2 ”, “cv1T1 ” is reference-related to “cv1T2 ” if T1 is the same type as T2 , or T1 is a base class of T2 . “cv1T1 ” is reference-compatible with “cv2T2 ” if T1 is reference-related to T2 and cv1 is the same cv-qualification as, or greater cv-qualification than, cv2. In all cases where the reference-related or reference-compatible relationship of two types is used to establish the validity of a reference binding, and T1 is a base class of T2 , a program that necessitates such a binding is ill-formed if T1 is an inaccessible [..] base class of T2.

这种参考绑定将因此总是失败,不管可用的任何转换函数。引用绑定不能用于私有继承。

您的显式调用是解决此问题的方法,但不再需要转换操作符:只需定义一个返回const-引用的getter即可。例如。

const B& b = a.getB(); 
3
const B& b = a; 

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

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

2

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

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

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

相关问题