这个班级成员的类型是什么?

时间:2013-08-10 08:55:45

标签: c++

我的代码是:

typedef double Money;
class Person
{
    Money get(){return a;}
private:
    typedef long double Money;
    Money a;
};

我定义了这个类,我想知道a的类型:doublelong 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

5 个答案:

答案 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类型为MoneyMoneylong 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 ++那样)。

相关问题