0

我有一个矢量类,如下所示:

class Vector3
{

 public:
   Vector3(){m_x = m_y = m_z = 0.0f;}
   Vector3(const float & i_x, const float & i_y, const float & i_z):
     m_x(i_x), 
     m_y(i_y),
     m_z(i_z)
     {}

   Vector3 operator+(const Vector3 & i_other);
private:
   float m_x;
   float m_y;
   float m_z;
};

Vector3::Vector3 Vector3::operator+(const Vector3 & i_other)
{
   float tx = m_x + i_other.m_x;
   float ty = m_y + i_other.m_y;
   float tz = m_z + i_other.m_z;
   return Vector3(tx, ty, tz);
}

显然,Vector3::operator+定义 synax 是错误的,因为返回类型是Vector3::Vector3,而不是Vector3Vector3::Vector3意味着有一个命名空间Vector3,并且在命名空间内有一个类Vector3。但是我这里只有一个类Vector3,没有命名空间。

我的问题是,在 Ubuntu 12.04 中,上面的语法无法编译(Ubuntu 的 g++ 编译器是 [gcc version 4.6.3])。但是,在 Mac 中,g++ 可以编译代码(Mac 的 g++ 编译器是 [gcc version 4.2.1])。另外,我在 Red Hat linux 机器上测试了这个语法,它也可以工作(g++ 版本是 [gcc 版本 4.4.6])

那么,是不是不同版本的gcc编译原理不同呢?或者,我在 Ubuntu 中的 g++ 坏了?

4

1 回答 1

2

较旧的编译器不正确。那里有点小惊喜。

它可能被解析Vector3::Vector3为注入类型名称。在 的范围内class Vector3 { },标识符Vector3指的是类,而不是构造函数(当然,除非您声明构造函数)。乍一看,您可能会认为它在返回类型中的含义相同,因为 §3.4/3(我在这里使用 C++11 标准)说

出于名称隐藏和查找的目的,类的注入类名称(第 9 条)也被认为是该类的成员。

深入挖掘,在 §3.4.3.1/2 中,

在构造函数是可接受的查找结果并且嵌套名称说明符指定类 C 的查找中:

— 如果在嵌套名称说明符之后指定的名称,当在 C 中查找时,是 C 的注入类名称(第 9 条)

该名称被认为是命名类 C 的构造函数。

使用注入的类名开始声明的上下文恰好与定义class {}范围外的构造函数相同,a la

class Vector3 { … };

Vector3::Vector3(){m_x = m_y = m_z = 0.0f;}

较旧的 GCC 注意到声明不是构造函数,然后采取了可行的后备路径。然而,这种回退是非法的,因为 C++ 指定在构造函数可能是查找结果的上下文中,它是唯一有效的查找结果。

很可能,一些用户花时间提交错误,而 GCC 开发人员花时间诊断、修复并编写测试用例。乘以复杂语言(如 C++)中的琐碎事物的数量,您就会开始欣赏编译器所付出的努力。

于 2013-01-24T02:52:13.920 回答