如何在成员初始化列表中调用引用成员的构造函数?

时间:2017-06-26 06:35:32

标签: c++

考虑这个例子:

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的参考成员BB有一个构造函数,它引用了类CA的构造函数接受类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的构造函数。我在这里做错了什么?

2 个答案:

答案 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;
    };