问题描述
#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;
}
在GCC 4.2中,我收到以下消息:
In GCC 4.2, I get this message:
In function 'int main()':
Line 16: error: 'B::B(const B&)' is private
compilation terminated due to -Wfatal-errors.
如果我从B中删除私有,我得到我期望的输出:
If I remove the "private" from B, I get the output I expect:
A Constructor
A Constructor
B Constructor
B Destructor
A Destructor
A Destructor
我的问题是:为什么做一个不被调用的方法private编译?这是标准规定吗?是否有解决方法?
My question is: why does making a method which isn't called private change whether this code compiles? Is this standard-mandated? Is there a workaround?
推荐答案
当前标准(C ++ 03)中的重要语句似乎在§8.5。 3,它解释了如何初始化引用(在这些引号中, T1
是被初始化的引用的类型, T2
是初始化器表达式的类型。)
The important verbiage in the current standard (C++03) seems to be in §8.5.3, which explains how references are initialized (In these quotes, T1
is the type of the reference being initialized and T2
is the type of the initializer expression).
- 引用绑定到由右值表示的对象(见3.10)或
-- The reference is bound to the object represented by the rvalue (see 3.10) or to a sub-object within that object.
- 临时类型 cv1 T2
],并且调用构造函数将整个右值对象复制到临时值中。引用绑定到临时或临时中的子对象。
-- A temporary of type "cv1 T2
" [sic] is created, and a constructor is called to copy the entire rvalue object into the temporary. The reference is bound to the temporary or to a sub-object within the temporary.
将用于创建副本的构造函数可调用无论副本
The constructor that would be used to make the copy shall be callable whether or not the copy is actually done.
因此,即使实现将引用直接绑定到临时对象,复制构造函数也必须可访问。
So, even if the implementation binds the reference directly to the temporary object, the copy constructor must be accessible.
请注意,在C ++ 0x中,根据。新语言(N3092§8.5.3):
Note that this is changed in C++0x, per the resolution of CWG defect 391. The new language reads (N3092 §8.5.3):
- 初始化器表达式是一个右值, cv1 T1
兼容 cv2 T2
,
-- the initializer expression is an rvalue and "cv1 T1
" is reference-compatible with "cv2 T2
,"
- T1
与 T2
没有引用相关,初始化器表达式可以隐式转换为类型 cv3 T3的右值
(通过枚举适用的转换函数(13.3.1.6)并通过重载解析(13.3)选择最佳转换函数来选择此转换),
-- T1
is not reference-related to T2
and the initializer expression can be implicitly converted to an rvalue of type "cv3 T3"
(this conversion is selected by enumerating the applicable conversion functions (13.3.1.6) and choosing the best one through overload resolution (13.3)),
到第一种情况下的初始化器表达式rvalue和第二种情况下的转换结果的对象(或者在任一种情况下,到对象的适当的基类子对象)。
then the reference is bound to the initializer expression rvalue in the first case and to the object that is the result of the conversion in the second case (or, in either case, to the appropriate base class subobject of the object).
第一种情况适用,引用是直接绑定到初始化器表达式。
The first case applies and the reference is "bound directly" to the initializer expression.
这篇关于意外的const引用行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!