我的代码是:
typedef double Money;
class Person
{
Money get(){return a;}
private:
typedef long double Money;
Money a;
};
我定义了这个类,我想知道a
的类型:double
或long double
?
函数get()
的返回类型是double
,是不是正确?
我已使用函数std:is_same
来测试a
typedef double Money;
class Person
{
public:
Money get(){return a;}
void test()
{
cout<<is_same<decltype(a), double>::value<<endl; // false
cout<<is_same<decltype(a), long double>::value<<endl; //true
}
private:
typedef long double Money;
Money a;
};
因此a
的类型为long double
。
答案 0 :(得分:3)
在标准中说:
7.1.3 typedef指定器[dcl.typedef]
在给定范围内,typedef指定者不得用于重新定义在该范围内声明的任何类型的名称以引用不同的类型。
这意味着C ++要求Money
在第一次看到并稍后重新评估时必须属于同一类型。
你的程序是无效的,因为第一次Money
被评估它的类型为double
,当它被重新评估时,它的类型为long double
...所有在类范围内......
例如,如果您删除了get()
个功能,则当您声明Money
时,long double
将被评估为a
。
从评论中,我试图解释更多我的意思:
实际上,两个typedef在不同的范围内定义。但是在Money
(对于get()
定义)的第一次评估期间,由于在全局范围内完成了typedef,其类型为double
。
稍后,使用第二个typedef,我们会将Money
重新定义为long double
类型。
这里我们试图在同一范围(类范围)中重新定义之前声明的类型。
似乎Visual Studio 2010和2012就可以了。
我用g ++ 4.2.1和4.8.1测试了它,我收到了这个错误:
error: declaration of ‘typedef long double Person::Money’
error: changes meaning of ‘Money’ from ‘typedef double Money’
答案 1 :(得分:1)
这是无效的C ++代码,因此您的问题没有答案。 C ++要求首次看到Money
时,以及稍后重新评估Money
时,两种情况下都是相同的类型。 GCC为此产生了一个硬错误。其他编译器可能会接受它,但如果他们这样做,标准就不会说明使用了哪种typedef。
如果您删除了get()
功能,则a
的类型为long double
,因为本地typedef会影响全局类型。在这种情况下,使用Money
之前会出现本地typedef,并且没有问题。
答案 2 :(得分:0)
该行
typedef long double Money;
是赠品
即。 a
类型为Money
,Money
为long double
答案 3 :(得分:0)
最简单的方法是检查它:
#include <iostream>
typedef char Money;
class Person
{
public:
void checkType()
{
if (sizeof(char) == sizeof(long))
{
std::cout << "This test is bullshit" << std::endl;
else if (sizeof(Money) == sizeof(char))
{
std::cout << "It's a char. Global scope is what matters" << std::endl;
}
else if (sizeof(Money) == sizeof(long))
{
std::cout << "It's a long. Inner scope is what matters" << std::endl;
}
}
private:
typedef long Money;
};
int main()
{
Person p;
p.checkType();
system("pause");
return 0;
}
答案是......长! (无论如何,在VS2012)
答案 4 :(得分:0)
我认为在这种情况下标准的适用部分是§3.3.7/ 1:2和3:
2)在S类中使用的名称N应在其上下文中引用相同的声明,并在完成的S范围内重新评估。违反此规则不需要诊断。
3)如果类中的重新排序成员声明在(1)和(2)下产生备用有效程序,则程序格式错误,不需要诊断。
在Money
的返回类型定义的上下文中,Person
定义中使用的名称Person::get
引用::Money
,但在完成时重新评估Person
的范围是指::Person::Money
。
同样,重新排序成员声明,使typedef
的{{1}}位于Person::Money
之前,产生一个备用有效程序。
因此,您的代码似乎格式不正确,但由于无需诊断,因此VC ++和gcc在这方面同样符合要求。我当然更喜欢将违规行为诊断出来(如gcc那样),而不是默默地接受(如VC ++那样)。