问题描述
初始化抽象类型的引用时,构造函数初始化列表中的{}初始化是如何不同于初始化的?下面的类Bar:
How is {} initialization in a constructor initialization list different from () initialization when initializing reference to abstract types? Take class Bar below:
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作为类型的情况,我都不在这里。
Reading through Stroustrup's C++11 book, I was under the impression that {} was the same as () in most all cases, except where there was an ambiguity between constructors that take std::initializer_list<> and other constructors, and cases where using auto as the type, neither of which I'm doing here.
推荐答案
简短答案:这是一个在C ++ 14中修复的标准错误,而g ++ 4.9有修复(追溯应用于C ++ 11模式)。
Short answer: This was a bug in the Standard which is fixed in C++14, and g++ 4.9 has the fix (retroactively applied to C++11 mode too). Defect Report 1288
这里有一个更简单的例子:
Here's a simpler example:
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
绑定到 x
;其实意思是创建一个临时并绑定一个引用。从C ++ 11 [dcl.init.ref] / 3:
In the text of C++11, the meaning of S const &y {x};
is not to bind y
to x
; in fact the meaning is to create a temporary and bind a reference to that. From C++11 [dcl.init.ref]/3:
这很傻,显然这个代码的意图是绑定 y
直接到
x
。在C ++ 14中,文本已更改:
This is pretty silly , clearly the intent of this code is to bind y
directly to x
. In C++14 the text was changed:
是与自身(或其基类之一)相关的引用,在我的样例中和你的实际代码中,它应该实际绑定正确。
Since a type is reference-related to itself (or one of its base classes), in my sample here and in your actual code, it should actually bind correctly.
您的错误消息来自编译器遵循C ++ 11字样,并试图从 base
创建一个临时表,以将引用绑定到;并且此操作失败,因为 base
是抽象类型。
Your error message comes from the compiler following the C++11 wording and attempting to create a temporary from base
to bind the reference to; and this fails because base
is of an abstract type.
这篇关于为什么C ++ 11不支持在构造函数初始化列表中的初始化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!