在初始化对抽象类型的引用时,构造函数初始化列表中的 {} 初始化与 () 初始化有何不同?拿下面的类吧:
class AbstractBase
{
public:
AbstractBase() {}
virtual ~AbstractBase() = default;
virtual void ab() = 0;
};
class Foo : public AbstractBase
{
public:
Foo() {}
void ab() {}
};
class Bar
{
public:
Bar(const AbstractBase& base) : myBase{base} {}
private:
const AbstractBase& myBase;
};
int main()
{
Foo f{};
Bar b{f};
}
编译的时候报错
test5.cpp: In constructor ‘Bar::Bar(const AbstractBase&)’:
test5.cpp:22:48: error: cannot allocate an object of abstract type ‘AbstractBase’
Bar(const AbstractBase& base) : myBase{base}
^
test5.cpp:2:7: note: because the following virtual functions are pure within ‘AbstractBase’:
class AbstractBase
^
test5.cpp:8:18: note: virtual void AbstractBase::ab()
virtual void ab() = 0;
换行
Bar(const AbstractBase& base) : myBase(base) {}
它编译并运行良好。
阅读 Stroustrup 的 C++11 书,我的印象是 {} 在大多数情况下都与 () 相同,除非在采用 std::initializer_list<> 的构造函数和其他构造函数之间存在歧义,以及使用 auto 作为类型的情况,我在这里都没有这样做。
最佳答案
简短回答:这是标准中的一个错误,已在 C++14 中修复,g++ 4.9 已修复(也可追溯应用于 C++11 模式)。 Defect Report 1288
这是一个更简单的例子:
struct S
{
int x;
S() { } // this causes S to not be an aggregate (otherwise aggregate
// initialization is used instead of list initialization)
};
S x = 5;
S const &y { x } ;
x = 6;
std::cout << y << std::endl; // output : 5
在C++11的文本中,S const &y {x};
的意思是不把y
绑定(bind)到x
;实际上意思是创建一个临时的并绑定(bind)一个引用。来自 C++11 [dcl.init.ref]/3:
Otherwise, if T is a reference type, a prvalue temporary of the type referenced by T is list-initialized, and the reference is bound to that temporary. [Note: As usual, the binding will fail and the program is ill-formed if the reference type is an lvalue reference to a non-const type. —end note ]
这很傻,很明显这段代码的目的是将y
直接绑定(bind)到x
。在 C++14 中,文本已更改:
Otherwise, if the initializer list has a single element of type E and either T is not a reference type or its referenced type is reference-related to E, the object or reference is initialized from that element;
由于类型与自身(或其基类之一)相关,因此在我的示例和您的实际代码中,它实际上应该正确绑定(bind)。
您的错误消息来自编译器,遵循 C++11 的措辞,并试图从 base
创建一个临时文件以将引用绑定(bind)到;这失败了,因为 base
是抽象类型。
关于c++ - 当 parent 初始化时,为什么构造函数初始化列表中的 C++11 花括号初始化不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26640866/