C++ 转换为从未使用过的基类

C++ 转换为从未使用过的基类,c++,c++11,base-class,explicit,typecast-operator,C++,C++11,Base Class,Explicit,Typecast Operator,我有两个类,一个是从另一个私有派生的(因为我不想公开基类的接口)。但是,稍后我想创建一个对基的引用 我可以用一个普通的成员函数base(),但不能用cast操作符,因为这个操作符从未被调用过 clang对此提出了警告,因为它说“永远不会有人叫它” 为什么cast运算符被私有元素忽略和覆盖? 这是语言上的不一致吗 事实上,我认为它有一个很好的解释,它公开了基础参考,而没有其他东西。 更重要的是,如果它起作用,它可能是显式的 class A{ int v_; public: void

我有两个类,一个是从另一个私有派生的(因为我不想公开基类的接口)。但是,稍后我想创建一个对基的引用

我可以用一个普通的成员函数
base()
,但不能用cast操作符,因为这个操作符从未被调用过

clang对此提出了警告,因为它说“永远不会有人叫它”

为什么cast运算符被私有元素忽略和覆盖? 这是语言上的不一致吗

事实上,我认为它有一个很好的解释,它公开了基础参考,而没有其他东西。 更重要的是,如果它起作用,它可能是显式的

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限定的)或void(可能是cv限定的)


在最后一行中显式调用操作符应该可以正常工作。但是标准要求它不会被隐式调用。@Cheersandhth.-Alf,说得好。实际上,它与clang一起工作,而不是与gcc一起工作,clang与自身不一致,因为它发出警告,永远不会使用它,然后它就被使用了!好的,我想规则是,即使不能从上下文访问私有接口,也永远不会自动回退到公共接口。这让我想起了成员函数不会自动回退
struct A{void f(){};结构B:A{private:void f(){};};B B;b、 f()//错误
。但我仍然认为这是有用途的(特别是现在有了
explicit
关键字。)@alfC访问控制从未用于过载解析等;相反,代码被解析,如果成员不可访问,那么它的格式就不正确。