2013-08-16 103 views
3

此代码不能用gcc 4.7.0编译:删除拷贝构造函数结果中删除默认的构造函数

class Base 
{ 
public: 
    Base(const Base&) = delete; 
}; 

class Derived : Base 
{ 
public: 
    Derived(int i) : m_i(i) {} 

    int m_i; 
}; 

的错误是:

c.cpp: In constructor ‘Derived::Derived(int)’: 
c.cpp:10:24: error: no matching function for call to ‘Base::Base()’ 
c.cpp:10:24: note: candidate is: 
c.cpp:4:2: note: Base::Base(const Base&) <deleted> 
c.cpp:4:2: note: candidate expects 1 argument, 0 provided 

换句话说,编译器不产生基类的默认构造函数,而是尝试调用删除的拷贝构造函数作为唯一可用的重载。

这是正常的行为吗?

+1

是的,因为如果任何构造函数是*用户声明*,则默认构造函数被抑制。 – Xeo

+1

为什么要删除一个被认为是构造函数声明的构造函数?这是违反直觉的。 – kounoupis

回答

8

C++ 11§12.1/ 5的状态:

默认构造一类XX类的构造,可以不使用参数被调用。如果没有用户声明的类X的构造函数,则不带参数的构造函数将隐式声明为默认值(8.4)。

您的Base(const Base&) = delete;算作用户声明的构造函数,因此它禁止生成隐式默认构造函数。解决方法当然是声明它:

Base() = default; 
+0

为什么一个被删除的构造函数会被视为一个构造函数的声明?这对我没有意义。删除的构造函数明确表示不允许定义这种构造函数(默认或不)。 – kounoupis

+1

我发现这个:[ISO/IEC JTC1 SC22 WG21 N2346](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm#delete),指出所有查找并且在删除的定义被记录之前会发生重载分辨率,因此这个答案是正确的。 – kounoupis