【问题标题】:Can a member of a class be named the same name as its type (another class)?可以将类的成员命名为与其类型(另一个类)相同的名称吗?
【发布时间】:2012-10-08 06:13:24
【问题描述】:

尝试在不同的编译器上编译以下代码会给我两个不同的结果:

struct S{};
struct T{S S;};
int main(){}

如您所见,在T 内部,我有一个与之前定义的类S 同名的对象。


在 GCC 4.7.2 上,I get the following errorT 内的 S S; 声明有关:

错误:“S T::S”的声明 [-fpermissive]
错误:从 'struct S' [-fpermissive] 更改 'S' 的含义

但是,将其移出课堂(或移入mainworks fine

struct S{};
S S;
int main(){}

它给我的错误究竟是什么意思?


在 Visual Studio 2012 中,整个程序编译并运行,没有任何错误。将其粘贴到 this Clang 3.0 compiler 也不会出错。

哪个是对的?我真的可以这样做吗?

【问题讨论】:

  • 啊,我明白了——我误读了诊断结果。
  • @ildjarn,这是一个相当奇怪的标志。它似乎反过来工作。通常,负责警告的标志出现在方括号中。
  • 别这样。重点是什么?迷惑?请注意,完成此操作后,如果没有明确限定命名空间,就不能再在成员函数中引用类型 S...
  • @DavidRodríguez-dribeas,我意识到这一点。我不打算这样做:)

标签: c++ g++ implementation clang visual-c++-2012


【解决方案1】:

gcc 是正确的,来自 [3.3.7 Class Scope]

在类 S 中使用的名称 N 应在其中引用相同的声明 上下文和在 S 的完整范围内重新评估时。否 违反此规则需要进行诊断。

但是,请注意no diagnostic is required,因此所有编译器都符合要求。

原因在于类作用域的工作方式。当您编写S S; 时,S整个 类中可见,并在您使用S 时改变其含义。

struct S{};
struct T{
    void foo()
    { 
        S myS; // Not possible anymore because S refers to local S
    }
    S S;
};

【讨论】:

  • IIRC 的基本原理是允许在类中定义类成员函数。如果名称的含义在类中发生变化,则在其中进行名称查找会很时髦。 (按原样已经够难了)。
  • 同样的例子与 C# 中的正确语义完美结合。 Smember 也可用于正确的语义。 C# 能够区分使用S 的上下文,但不清楚为什么 C++ 编译器不能这样做。
【解决方案2】:

@JesseGood 提供了一个完整的答案,但如果你真的想这样做没有任何错误,你可以使用类型的全名,它的工作原理如下:

struct S {};
struct T { ::S S; };
int main() {return 0;}

不,没有错误,因为您班级中的ST::S,其类型是::S

【讨论】:

    【解决方案3】:

    此代码格式错误,无需诊断。就像诊断所说的那样,如果声明使用了一个名称,并且该名称的含义与在类定义末尾查找时的含义不同,则程序是错误的,不需要诊断。

    【讨论】:

    • 又是我提升自己的一天! +1
    猜你喜欢
    • 2021-02-13
    • 1970-01-01
    • 1970-01-01
    • 2011-06-11
    • 2012-04-21
    • 2021-12-31
    • 1970-01-01
    • 2020-08-24
    相关资源
    最近更新 更多