我有一个像这样的 vector 类:
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+
定义语法是错误的,因为返回类型是Vector3::Vector3
,而不是Vector3
。 Vector3::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++ 坏了?
最佳答案
旧的编译器不正确。没什么惊喜。
它可能将 Vector3::Vector3
解析为注入(inject)类型名称。在 class Vector3 { }
的范围内,标识符 Vector3
指的是类,而不是构造函数(当然,声明构造函数时除外)。乍一看,您可能认为它在返回类型中意味着相同的东西,因为 §3.4/3(我在这里使用 C++11 标准)说
The injected-class-name of a class (Clause 9) is also considered to be a member of that class for the purposes of name hiding and lookup.
深入挖掘,在 §3.4.3.1/2 中,
In a lookup in which the constructor is an acceptable lookup result and the nested-name-specifier nominates a class C:
— if the name specified after the nested-name-specifier, when looked up in C, is the injected-class-name of C (Clause 9)
the name is instead considered to name the constructor of class C.
以注入(inject)类名开始声明的上下文恰好与在 class {}
范围之外定义构造函数时相同,a la
class Vector3 { … };
Vector3::Vector3(){m_x = m_y = m_z = 0.0f;}
较旧的 GCC 注意到声明不是构造函数,然后采用了可行的后备路径。然而,这种回退是非法的,因为 C++ 指定在构造函数可能是查找结果的上下文中,它是唯一有效的查找结果。
很可能,某些用户花时间提交错误,而 GCC 开发人员花时间诊断、修复它并编写测试用例。乘以 C++ 等复杂语言中琐碎的数量,您就会开始欣赏编译器所付出的努力。
关于C++类函数返回类型定义,返回一个类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14492878/