意外的const引用行为

Zac*_*nce 8 c++ gcc4

#include <iostream>

class A { 
  public:  
    A(){ cerr << "A Constructor" << endl; }  
    ~A(){ cerr << "A Destructor" << endl; }  
    A(const A &o){ cerr << "A Copy" << endl; } 
    A& operator=(const A &o){ cerr << "A Assignment" << endl; return *this; }
};


class B : public A { 
  public:  
    B() : A() { cerr << "B Constructor" << endl; }  
    ~B(){ cerr << "B Destructor" << endl; }
  private:
    B(const B &o) : A() { cerr << "B Copy" << endl; } 
    B& operator=(const B &o){ cerr << "B Assignment" << endl; return *this; }
};

int main() {  
  A a;  
  const A &b = B();  
  return 0; 
}
Run Code Online (Sandbox Code Playgroud)

在GCC 4.2中,我收到此消息:

In function 'int main()':
Line 16: error: 'B::B(const B&)' is private
compilation terminated due to -Wfatal-errors.
Run Code Online (Sandbox Code Playgroud)

如果我从B中删除"私有",我得到我期望的输出:

A Constructor
A Constructor
B Constructor
B Destructor
A Destructor
A Destructor
Run Code Online (Sandbox Code Playgroud)

我的问题是:为什么制作一个不被称为私有的方法会改变这个代码是否编译?这是标准规定的吗?有解决方法吗?

Jam*_*lis 4

当前标准(C++03)中的重要措辞似乎在 \xc2\xa78.5.3 中,它解释了如何初始化引用(在这些引号中,T1是正在初始化的引用的类型,T2是初始化程序的类型表达)。

\n
\n

T2如果初始值设定项表达式是具有类类型的右值,并且“ cv1 T1”与“ ”引用兼容cv2 T2,则引用将通过以下方式之一进行绑定(该选择是实现定义的):

\n

-- 引用绑定到右值表示的对象(参见 3.10)或该对象内的子对象。

\n

cv1 T2--创建“”类型的临时对象[原文如此],并调用构造函数将整个右值对象复制到临时对象中。该引用绑定到临时对象或临时对象中的子对象。

\n

无论复制是否实际完成,用于进行复制的构造函数都应该是可调用的。

\n
\n

因此,即使实现将引用直接绑定到临时对象,复制构造函数也必须可访问。

\n

请注意,根据CWG 缺陷 391的解决方案,这在 C++0x 中发生了更改。新语言如下(N3092 \xc2\xa78.5.3):

\n
\n

否则,如果T2是类类型并且

\n

-- 初始化表达式是一个右值,并且“ ”与“ ,”cv1 T1引用兼容cv2 T2

\n

--T1与引用无关,T2并且初始值设定项表达式可以隐式转换为 " 类型的右值cv3 T3"(通过枚举适用的转换函数 (13.3.1.6) 并通过重载决策 (13.3) 选择最佳转换函数来选择此转换) ,

\n

那么该引用在第一种情况下绑定到初始值设定项表达式右值,在第二种情况下绑定到作为转换结果的对象(或者在任一情况下绑定到该对象的相应基类子对象)。

\n
\n

适用第一种情况,并且引用“直接绑定”到初始值设定项表达式。

\n