我有两个类,一个是从另一个私有派生的(因为我不想暴露基础的接口)。但是后来我想创建一个对base的引用。
我可以使用普通的成员函数base()
但不能使用强制转换运算符,因为从不调用此运算符
clang警告它,因为它说“永远不会被称为”。
为什么抛出运算符会被私有元素忽略和覆盖?这是语言的不一致吗?
实际上,我认为它有一个公开基础参考,没有别的。更重要的是,如果它有效,它可能是explicit
。
class A{
int v_;
public:
void f(){}
};
class B : A{ // A is private base because I don't want the f() interface
int w_;
public:
A const& base() const{return *this;}
/*explicit*/ operator A const&() const{return *this;} // never called, warning in clang
};
int main(){
A a = {};
B b = {};
A const& a2 = b.base();
A const& a3 = b; // bad, But why?
A const& a4{b}; // explict doesn't help
A const& a5 = b.operator A const&(); // works in clang (but with a contradictory warning), doesn't work with gcc
}
在a3
和a4
的情况下,您正在使用左值初始化引用。在这种情况下,如果引用的类型是初始化程序类型的基类,则引用直接绑定到初始化程序,则不涉及转换(C ++ 17 [dcl.init.ref] / 5)。
由于无法访问基类,因此程序格式错误(dcl.init.ref / 4)。
我不确定a5
中的访问检查规则,虽然它在实践中似乎没有实际意义,因为你不会设计代码,所以有人必须编写该语法。
另见[class.conv.fct] / 1:
转换函数从不用于将(可能是cv限定的)对象转换为(可能是cv限定的)相同的对象类型(或对它的引用),转换为该类型的(可能是cv限定的)基类(或引用它)或(可能是cv-qualified)void。