为什么重新定义固定大小的静态数组是必需的/有效的

Why is redefining a fix sized static array required/works?

本文关键字:数组 静态 有效 新定义 定义 为什么      更新时间:2023-10-16

我希望你们中的一个人能向我解释为什么编译器要求我在编译单元中重新定义一个静态固定长度数组,尽管我已经在头中这样做了。这里有一个例子:

MyClass.h:

#ifndef MYCLASS_H
#define MYCLASS_H
class MyClass {
private:
    static char myPrecomputeTable[256];
}
#endif

MyClass.cpp

#include "MyClass.h"
char MyClass::myPrecomputeTable[256];

如果我删除MyClass.cpp中的重新定义,链接器会抱怨myPrecomputeTable未定义。语法似乎是多余的。有人能向我解释一下为什么编译器/链接器需要这个定义吗?

编辑:

对不起,我想我不清楚我困惑的是什么。我理解声明/定义的概念,更有趣的是定义数组的大小。在定义和声明中,我都必须定义似乎多余的大小。

编辑:

我做了更多的挖掘,发现这个主题的许多方法都是编译器友好的。编译:

MyClass.h
class MyClass {
    static char myPrecomputeTable[256];
};
MyClass.cpp
char MyClass::myPrecomputeTable[256];

编译:

MyClass.h
class MyClass {
    static char myPrecomputeTable[];
};
MyClass.cpp
char MyClass::myPrecomputeTable[256];

编译:

MyClass.h
class MyClass {
    static char myPrecomputeTable[256];
};
MyClass.cpp
char MyClass::myPrecomputeTable[];

不编译:

MyClass.h
class MyClass {
    static char myPrecomputeTable[512];
};
MyClass.cpp
char MyClass::myPrecomputeTable[256];

大小必须在标头或类中定义,或者同时在两者中定义,但编译器足够聪明,可以停止大小冲突。

在标题中:

class MyClass {
private:
    static char myPrecomputeTable[256];
}

这是一个声明

在.cpp中:

char MyClass::myPrecomputeTable[256];

定义

声明提供符号的基本属性:其类型和名称。

定义提供了该符号的所有细节——如果它是一个函数,它会做什么;如果它是一个类,它有哪些字段和方法;如果它是一个变量,那么该变量存储在哪里。

通常,编译器只需要有一个声明就可以将文件编译为对象文件,期望链接器可以从另一个文件中找到定义。如果没有源文件定义过一个符号,但它是声明的,那么在链接时您将收到抱怨未定义符号的错误。

一个很好的链接来理解两者之间的区别:http://www.cprogramming.com/declare_vs_define.html


来自标准:

3.1声明和定义[basic.def]

  1. 声明可以将一个或多个名称引入翻译单元,也可以重新声明以前声明引入的名称。如果是,则声明指定这些名称的解释和属性。声明也可能具有以下效果:

    • 静态断言(第7条)
    • 控制模板实例化(14.7.2)
    • 属性的使用(第7条),以及
    • 什么都没有(在空声明的情况下)
  2. 声明是定义,除非它在不指定函数体的情况下声明函数,它包含extern说明符或链接规范且既不是初始值设定项也不是function-body;它在类定义中声明静态数据成员,或者它是typedef声明using声明ttribute声明空声明用指令。

头文件中的第一个只是一个声明,告诉编译器该成员存在于包括头文件的所有其他源文件中。

源文件中的第二个是实际的定义,链接器在将整个项目链接到单个可执行文件时需要它。


在必须告诉编译器两次大小的情况下,这就是指定语言的工作方式。你(或任何人)对此无能为力。

但是,您可以使用typedef来解决它:

class MyClass
{
    typedef char PrecomputeTable_t[256];
    static PrecomputeTable_t myPrecomputeTable;
};
...
MyClass::PrecomputeTable_t MyClass::myPrecomputeTable;