考虑这个例子:
class C {};
class B {
public:
B(C& c) : c_(c) {};
private:
C& c_;
};
class A {
public:
A(C& c) : b(c) {};
private:
B& b;
};
A
有一个类b
的参考成员B
。 B
有一个构造函数,它引用了类C
。 A
的构造函数接受类C
的引用,并尝试通过使用b
调用后者的构造函数来初始化c
。
但是clang抱怨说:
wtf.cpp:12:13: error: non-const lvalue reference to type 'B' cannot bind to a value of unrelated type 'C'
A(C& c) : b(c) {};
^ ~
1 error generated.
这听起来几乎就像clang认为我将c
分配给b
,但我的目的是用B
调用c
的构造函数。我在这里做错了什么?
答案 0 :(得分:1)
您描述的内容不仅限于初始化列表,而是通常的参考构造。以下内容不应编译:
class C
{};
class B
{
public:
B(C& c)
: c_(c)
{}
private:
C& c_;
};
int main()
{
C c;
B b0(c); // This works because you actually create an object of type B.
B& b1(c); // Error, cannot construct reference to B from C.
B& b2 = c; // Same as above, only a different notation.
// You cannot write a constructor of B to make these lines work,
// because you do not create an object of type B.
}
类B
的对象可以从对C
对象的引用构造,但同样不适用于引用。只能从相同类型的对象或继承层次结构中的类型创建引用。
这正是引用的要点:您不构造对象。您只需为在其他位置创建的对象引入新名称。
答案 1 :(得分:1)
你做不到。实际上,引用接近于不可修改的指针。这意味着B&
只能引用类B
的对象或B
的子类。并没有像参考文献的构建那样。
您可以从B
引用构造一个临时C
对象,但是您无法使用临时对象初始化引用,因为一旦引用将被初始化,引用的对象将是破坏。
所以你必须在A:
中存储一个真实的对象,而不是一个参考 class A {
public:
A(C& c) : b(c) {};
private:
B b;
};