C++错误 - "成员初始化表达式列表被视为复合表达式"

19

我遇到了一个我不熟悉的C++编译器错误。可能是一个非常愚蠢的错误,但我无法确定具体原因。

错误信息:

test.cpp:27: error: member initializer expression list treated as compound expression
test.cpp:27: warning: left-hand operand of comma has no effect
test.cpp:27: error: invalid initialization of reference of type ‘const Bar&’ from expression of type ‘int’

代码:

  1 #include <iostream>
  2
  3 class Foo {
  4 public:
  5         Foo(float f) :
  6                 m_f(f)
  7         {}
  8
  9         float m_f;
 10 };
 11
 12 class Bar {
 13 public:
 14         Bar(const Foo& foo, int i) :
 15                 m_foo(foo),
 16                 m_i(i)
 17         {}
 18
 19         const Foo& m_foo;
 20         int m_i;
 21 };
 22
 23
 24 class Baz {
 25 public:
 26         Baz(const Foo& foo, int a) :
 27                 m_bar(foo, a)
 28         {}
 29
 30         const Bar& m_bar;
 31 };
 32
 33 int main(int argc, char *argv[]) {
 34         Foo a(3.14);
 35         Baz b(a, 5.0);
 36
 37         std::cout << b.m_bar.m_i << " " << b.m_bar.m_foo.m_f << std::endl;
 38
 39         return 0;
 40 }
注意: 看起来编译器正在类似这里的第27行中评估逗号: http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=/com.ibm.xlcpp8l.doc/language/ref/co.htm 编辑: 好的,我已经理解了Alan解释的问题。现在,为了额外的虚构点,有人能解释一下编译器(g++)是如何得出它给出的错误消息的吗?

g++是如何产生错误信息的?毫无头绪。Sun Studio会给出以下错误信息:line 27: Error: Too many initializers for m_bar.这个错误信息更加详细。简单来说,许多编译器的错误信息都有些难以理解。 - Glen
对于额外的分数:代码出现了错误,因为它正在尝试使用 (foo,a) 的构造函数来构造 Bar。错误消息告诉你 foo 将被忽略,并且它无法将 int a 转换为 Bar。我知道这是一个古老的问题,但你标记的答案是不正确和误导的。我发布了代码,说明了如何保持声明 m_bar 不变并使其编译。 - Tod
4个回答

21

m_bar是一个引用(reference),因此你不能构造它。

正如其他人所指出的,你可以使用引用所指向的对象进行初始化,但你不能像你试图做的那样构造一个引用。

将第30行更改为

const Bar m_bar

代码可以被正确编译/运行。


5

m_bar被声明为“const引用”,因此无法使用您提供的构造函数进行实例化。

考虑将m_bar作为成员变量,或将预先构建的Bar对象传递给构造函数。


4
你可以在以下代码中更清楚地看到问题:

struct B {
    B( int a, int x  ) {}
};

int main() {
    const B & b( 1, 2);
}

以下是使用g++编译时产生的错误信息:
t.cpp: In function 'int main()':
t.cpp:6: error: initializer expression list treated as compound expression
t.cpp:6: error: invalid initialization of reference of type 'const B&' from expression of type int'

VC++ 6.0 给出了更加晦涩的错误信息:

 error C2059: syntax error : 'constant'

简单来说,你不能像那样初始化引用。

0

(编辑:请参见评论) 虽然这个问题很旧,但为了未来的读者,我要指出标记为答案的项目是不正确的。确实可以构造一个引用。

在初始化器行中,代码m_bar(foo, a)试图使用(foo,a)作为m_bar的构造函数。错误告诉你foo将被忽略,并且你不能用int a构造一个Bar。以下正确的语法将编译无误:

m_bar (*new Bar(foo,a))

1
被标记为正确的答案肯定是正确的!虽然可以构建一个引用,但并不意味着应该这样做!(尽管你在关于编译器消息的正确方向上,我会给你授权!) - Troyseph
@Tod 我喜欢你的思路(即逗号可以被解释为表达式的一部分,而不是两个参数之间的分隔符)- 你的编译器或许可以给出这样的提示。但我仍然不能同意你的例子表明“引用可以被构造”。你构造的是一个临时对象(new Bar(foo, a)),引用只绑定到这个临时对象上(这通常不是我们想要做的事情)。 - Artur Opalinski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接