谁能解释为什么以下代码不编译(ON G ++(GCC)3.2.3 20030502(Red Hat Linux 3.2.3-49))?

struct X {
public:
   enum State { A, B, C };

   X(State s) {}
};

int main()
{
   X(X::A);
}

我收到的消息是:

jjj.cpp:在函数'int main()'中:
jjj.cpp:10:'xx :: a'不是'struct x'的静态成员
jjj.cpp:10:无匹配函数呼叫'x :: x()'
jjj.cpp:1:候选人是:x :: x(const x&)
jjj.cpp:5:x :: x(x :: state)`

这是不良代码还是编译器错误?

Neil+Konrad解决的问题。请参阅下面尼尔回答的评论。

有帮助吗?

解决方案

X(X::A);

正在被视为ASA函数声明。如果您真的想要此代码,请使用:

(X)(X::A);

其他提示

您已经忘记了定义中的变量名称:

int main()
{
   X my_x(X::A);
}

您的代码使编译器感到困惑,因为从语法上它无法将其与函数声明区分开(返回 X 和过去 X::A 作为论点)。如有疑问,C ++编译器始终会歧义声明。

解决方案是在周围引入多余的括号 X 由于编译器禁止括号围绕类型(而不是构造电话等):

(X(X::A));

只是为了使晶体清楚发生。看这个示例

int main() {
    float a = 0;
    {
        int(a); // no-op?
        a = 1;
    }
    cout << a;
}

它会输出什么?好吧,它将输出 0. 。这 int(a) 以上可以通过两种不同的方式解析:

  • 铸造并丢弃结果
  • 声明一个称为的变量 a. 。但是忽略标识符周围的括号。

当出现这种情况时,该编译器在语句中使用了函数式演员表,并且看起来也像是声明时,它将始终将其视为声明。当句法上不能是声明(编译器将查看整个行以确定这一点)时,它将被视为表达式。因此,我们正在分配内部 a 上面,离开外部 a 在零。

现在,您的情况就是这样。您正在尝试(偶然地)声明一个名称的标识符 A 在一个称为的课堂中 X:

X (X::A); // parsed as X X::A;

然后,编译器继续抱怨未声明为默认构造函数,因为静态是默认的。但是,即使您有X的默认构造函数,它当然仍然是错误的,因为 A 是X的静态成员,也可以在块范围内定义/声明X的静态成员。

你可以做到 不是 通过做几件事,看起来像是声明。首先,您可以帕伦(Paren)整个表达式,这使得它看起来不再像声明了。或者只是paren铸造的类型。其他答案中都提到了这两种歧义:

(X(X::A)); (X)(X::A)

当您尝试实际声明对象时,存在类似但独特的歧义。看看这个示例:

int main() {
    float a = 0;
    int b(int(a)); // object or function?
}

因为 int(a) 可以是称为参数的声明 a 浮点变量的明确转换为int,编译器再次决定这是声明。因此,我们碰巧声明了一个称为的函数 b, ,它采用整数参数并返回整数。基于以上的歧义,有几种可能歧义的可能性:

int b((int(a))); int b((int)a);

您应该将一个对象声明为

X x(X::A);

代码中的错误。

这两条线中的任何一个都对我有用:

X obj(X::A);
X obj2 = X(X::A);

正如尼尔·巴特沃思(Neil Butterworth)指出的那样, X(X::A) 被视为函数声明。如果您真的想要一个匿名对象, (X)(X::A) 将构造X对象并立即删除它。

当然,您可以做这样的事情:

int main()
{
    // code
    {
    X temp(X::A);
    }
    // more code
}

这将更加可读性,并且基本上具有相同的效果。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top