1

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

MyClass.h:

#ifndef MYCLASS_H
#define MYCLASS_H

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

#endif

我的类.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];

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

4

2 回答 2

6

在标题中:

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符或链接规范,既不是初始化程序也不是函数体,它在类定义中声明静态数据成员,它是一个类name 声明,它是opaque-enum-declaration,或者它是typedef 声明using-declaration, static_assert-declaration ,attribute-declarationempty-declarationusing-directive

于 2013-08-01T14:25:17.157 回答
2

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

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


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

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

class MyClass
{
    typedef char PrecomputeTable_t[256];

    static PrecomputeTable_t myPrecomputeTable;
};

...

MyClass::PrecomputeTable_t MyClass::myPrecomputeTable;
于 2013-08-01T14:23:53.683 回答