【问题标题】:Declaring a variable with "class " keyword vs Declaring one without "class" keyword in function signatures在函数签名中声明一个带有“class”关键字的变量与声明一个没有“class”关键字的变量
【发布时间】:2014-03-19 18:39:52
【问题描述】:

这两种方法有什么区别?

有时我收到编译时错误,抱怨编译器无法识别 函数签名中的一些类类型,那么如果我在各个变量前面加上关键字“class”,总是可以解决这种编译时错误。

例如,如果编译器在

中无法识别类型 Client
void recv( Client * c )

如果我把它改成

void recv( class Client * c )

问题解决了。

很抱歉,因为我随机提出了​​这个问题,所以我无法提出一个具体的例子。

【问题讨论】:

  • 从未听说过。你能提供一个显示此错误的SSCCE 吗?

标签: c++ class compiler-errors syntax-error keyword


【解决方案1】:

在类型参数声明中使用关键字class、struct、enum称为详细类型说明符。它在声明函数的范围内引入了新类型。 类似于前向声明。

这种声明还有另一种用法。例如,如果对象名称或函数名称隐藏了同名的类或枚举。例如

struct A {};

A A; // now A is seen as an identifier of the object

void f( struct A );

【讨论】:

  • 所以在这种情况下,我们需要在函数 f 的签名中使用关键字 struct 来区分 A 和第二行中声明的变量名 A。
【解决方案2】:

在这种情况下

void recv(Client * c)

编译器查找Client 的声明。如果找不到,就会报错。您可以通过前向声明来解决它,如下所示

class Client;
void recv(Client * c)

虽然我没有见过第二种情况,但看起来那也是在这里声明类Client。

【讨论】:

    【解决方案3】:

    如果您需要在参数前加上class,这意味着编译器还不知道有一个名为Client 的类。举一个人为的例子:

    int main(int argc, char *argv[])
    {
       MyClass m;
    
       return 0;
    }
    
    class MyClass
    {
    };
    

    因为MyClass 是在main 函数之后声明的,所以main 函数在尝试创建变量m 时并不知道名为MyClass 的类,因此您的程序将拒绝编译。

    要解决这个问题,您通常会使用前向声明:

    class MyClass; // <-- Forward declare MyClass.
    
    int main(int argc, char *argv[])
    {
       MyClass m;
    
       return 0;
    }
    
    class MyClass
    {
    };
    

    在您的情况下,在函数参数类型之前使用 class 关键字本质上是为您向前声明类名。

    【讨论】:

    • 那么这是否意味着我也可以在文件的开头预先声明类 Client 而不必像上面那样在函数签名中使用详细的类型说明符?
    • @takwing - 是的,我希望如此。
    【解决方案4】:

    编译器必须知道函数参数的类型。由于您显然没有通过包含 Client 的标头来提供定义,因此您必须提供前向声明。这就是您在第二个示例中所做的(以一种不寻常的方式),因此编译器知道,Client 是一个类。由于您只使用了一个指针,因此声明就足够了,此时您不需要定义。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-16
      • 1970-01-01
      • 2011-09-12
      • 1970-01-01
      • 2021-08-02
      • 1970-01-01
      • 2014-10-08
      • 1970-01-01
      相关资源
      最近更新 更多