4

以下程序用 g++ 4.6 编译,产生错误

request for member ‘y’ in ‘a2’, which is of non-class type ‘A<B>(B)’

在最后一行:

#include <iostream>

template <class T> class A
{
public:
  T y;
  A(T x):y(x){}
};

class B
{
public:
  int u;
  B(int v):u(v){}
};

int main()
{
  int v = 10;
  B b1(v);

  //works
  A<B> a1(b1);

  //does not work (the error is when a2 is used)
  A<B> a2(B(v));

  //works
  //A<B> a2((B(v)));

  std::cout << a1.y.u << " " << a2.y.u << std::endl;    
}

从代码中包含的工作变体可以看出,在 A 的构造函数的参数周围添加括号可以解决问题。

我已经看到由于将构造函数调用解释为函数声明而导致的一些相关错误,例如在创建一个没有构造函数参数但带有大括号的对象时:

myclass myobj();

但在我看来

A<B> a2(B(v));

不能解释为函数声明。

有人可以向我解释发生了什么吗?

4

4 回答 4

8

这是编译器将其解释为函数声明的最令人头疼的解析情况。A<B> a2(B(v))这样:

A<B>是返回类型
a2是函数名
B是参数的类型
v是参数名

所以,当你在做

std::cout << a1.y.u << " " << a2.y.u << std::endl;

编译器不认为a2.y.u是一个类,这就是你收到non-class type错误的原因。

此外,由于在函数声明中不允许使用双括号,因此该版本A<B> a2((B(v)));有效,因为编译器不再将其解释为函数声明,而是作为变量声明。

于 2012-06-21T12:54:55.077 回答
2

我认为您被“最令人烦恼的解析”所困扰,这意味着它A<B> a2(B(v));被解析为函数声明而不是变量声明。

于 2012-06-21T12:54:39.447 回答
2

如以下代码示例所示:

int a (int(v)) {
    return v;
}

int main() {
    std::cout << a(5); //prints 5
}

那一行确实是一个宣言。在这个例子中,参数是 typeint和 named v。将其与您的代码相关联,参数是 typeB并命名为v. 这就是为什么当你使用双括号时会得到类似的行为:因为它是同一件事!

于 2012-06-21T12:54:39.653 回答
2

这是一个函数声明:

A<B> a2(B(v));
//is same as:
A<B> a2(B v);

//consider:
int foo(int v);
int foo(int (v));
于 2012-06-21T12:55:45.100 回答