在c++标头中声明数组并在cpp文件中定义它?

时间:2021-01-29 15:06:33

This is probably a really simple thing but I'm new to C++ so need help.

这可能是一件非常简单的事情,但是我是c++新手,所以需要帮助。

I just want to declare an array in my C++ header file like:

我只想在我的c++头文件中声明一个数组:

int lettersArr[26];

and then define it in a function in the cpp file like:

然后在cpp文件中的函数中定义它,如:

    lettersArr[26] = { letA, letB, letC, letD, letE, letF, letG, letH,
        letI, letJ, letK, letL, letM, letN, letO, letP, letQ, letR, letS,
        letT, letU, letV, letW, letX, letY, letZ };

but this doesn't work.

但这是行不通的。

Have I got the syntax wrong or something? What is the correct way to to this?

我语法有问题吗?正确的方法是什么?

Thanks a lot.

非常感谢。

7 个解决方案

#1


22  

Add extern to the declaration in the header file.

将extern添加到头文件中的声明。

extern int lettersArr[26];

(Also, unless you plan to change the array, consider also adding const.)

(另外,除非您打算更改数组,否则还可以考虑添加const。)

The definition must have a type. Add int (or const int):

定义必须有一个类型。增加int(或const int):

int lettersArr[26] = { letA, /*...*/ };

#2


4  

Header:

标题:

extern int lettersArr[];

Source at the global scope:

全球范围的来源:

int lettersArr[26] = { letA, letB, letC, letD, letE, letF, letG, letH,
    letI, letJ, letK, letL, letM, letN, letO, letP, letQ, letR, letS,
    letT, letU, letV, letW, letX, letY, letZ };

or if you really want to do it in a function:

或者如果你真的想用函数来做:

Source at global scope:

源在全球范围:

int lettersArr[26];

Source in function:

源的功能:

int localLettersArr[26] = { letA, letB, letC, letD, letE, letF, letG, letH,
    letI, letJ, letK, letL, letM, letN, letO, letP, letQ, letR, letS,
    letT, letU, letV, letW, letX, letY, letZ };

memcpy (lettersArr, localLettersArr, sizeof (localLettersArr));

#3


2  

Change what you have in the header to:

将标题中的内容更改为:

extern int lettersArr[26];

so that it will become a declaration, not a definition.

因此它将成为一个声明,而不是定义。

#4


1  

Other have described how the array initialization can be moved to an implementation file, which is not exactly answering your question, but is a workaround that's useful to know.

其他人描述了如何将数组初始化移动到实现文件中,这并不能完全回答您的问题,但这是一个有用的解决方案。

I just want to declare an array in my C++ header file

我只想在c++头文件中声明一个数组

If you really want to have the array all in your header file, including having the initialization in your header file, then you can

如果您真的希望在头文件中包含所有的数组,包括在头文件中进行初始化,那么您可以。

  • give it internal linkage by using static, or

    通过使用静态,或者,给它内部链接。

  • use a local static in an inline function (which supports effectively external linkage), or

    在内联函数中使用本地静态(它支持有效的外部链接),或者

  • use a little template trick (also supports external linkage).

    使用一个小模板技巧(也支持外部链接)。

The last two solutions are workarounds for the lack of "inline" data in C++. That is, the ability to define the same namespace scope object in more than one translation unit. You have that for functions, via inline, but unfortunately not for objects: without employing some workaround the linker will just protest about multiple definitions.

最后两个解决方案是解决c++中缺少“内联”数据的问题。即在多个转换单元中定义相同名称空间范围对象的能力。对于函数,可以通过内联实现,但不幸的是对于对象:如果不使用一些变通方法,链接器只会*多个定义。

Internal linkage

This is generally not a good solution. It creates one array in each translation unit where the header is included. But it's preferable for relatively small const objects because it's so simple:

这通常不是一个好的解决方案。它在包含头的每个转换单元中创建一个数组。但对于相对较小的const对象,它更可取,因为它非常简单:

#include <stddef.h>
#include <iostream>

int const   letA    = 'A';
int const   letB    = 'B';
int const   letC    = 'C';
int const   letD    = 'D';
int const   letE    = 'E';
int const   letF    = 'F';
int const   letG    = 'G';
int const   letH    = 'H';
int const   letI    = 'I';
int const   letJ    = 'J';
int const   letK    = 'K';
int const   letL    = 'L';
int const   letM    = 'M';
int const   letN    = 'N';
int const   letO    = 'O';
int const   letP    = 'P';
int const   letQ    = 'Q';
int const   letR    = 'R';
int const   letS    = 'S';
int const   letT    = 'T';
int const   letU    = 'U';
int const   letV    = 'V';
int const   letW    = 'W';
int const   letX    = 'X';
int const   letY    = 'Y';
int const   letZ    = 'Z';

static int lettersArr[26]   =
{
    letA, letB, letC, letD, letE, letF, letG, letH,
    letI, letJ, letK, letL, letM, letN, letO, letP, letQ, letR, letS,
    letT, letU, letV, letW, letX, letY, letZ
};

int main()
{
    using namespace std;
    for( int i = 0;  i < 26;  ++i )
    {
        cout << char( lettersArr[i] );
    }
    cout << endl;
}

Local static in inline function

This is probably the generally "best" solution, to use when there is no overriding reason for choosing one of the other solutions. One nice thing is that it's easy to provide dynamic initialization. Here I've just assumed that you will never store 0 in the array (add some extra checking logic if that assumption doesn't hold):

这可能是通常的“最佳”解决方案,当没有压倒一切的理由选择其他解决方案时使用。一件好事是提供动态初始化很容易。这里我假设您永远不会在数组中存储0(如果这个假设不成立,添加一些额外的检查逻辑):

#include <stddef.h>
#include <iostream>

template< class Type, int n >
int countOf( Type (&)[n] ) { return n; }

typedef int LettersArray[26];

inline LettersArray& lettersArrayRef()
{
    static LettersArray theArray;

    if( theArray[0] == 0 )
    {
        // Assuming normal ASCII-based character set with contiguous alpha.
        for( int i = 0;  i < countOf( theArray );  ++i )
        {
            theArray[i] = i + 'A';
        }
    }
    return theArray;
}

static LettersArray&    lettersArr  = lettersArrayRef();

int main()
{
    using namespace std;
    for( int i = 0;  i < 26;  ++i )
    {
        cout << char( lettersArr[i] );
    }
    cout << endl;
}

Template trick

The template trick works because the standard's ODR, One Definition Rule, makes a special exemption for templates:

模板技巧之所以有效,是因为标准的ODR(定义规则之一)对模板进行了特殊的豁免:

#include <stddef.h>
#include <iostream>

int const   letA    = 'A';
int const   letB    = 'B';
int const   letC    = 'C';
int const   letD    = 'D';
int const   letE    = 'E';
int const   letF    = 'F';
int const   letG    = 'G';
int const   letH    = 'H';
int const   letI    = 'I';
int const   letJ    = 'J';
int const   letK    = 'K';
int const   letL    = 'L';
int const   letM    = 'M';
int const   letN    = 'N';
int const   letO    = 'O';
int const   letP    = 'P';
int const   letQ    = 'Q';
int const   letR    = 'R';
int const   letS    = 'S';
int const   letT    = 'T';
int const   letU    = 'U';
int const   letV    = 'V';
int const   letW    = 'W';
int const   letX    = 'X';
int const   letY    = 'Y';
int const   letZ    = 'Z';

template< class Dummy >
struct Letters_
{
    static int  array[26];
};

template< class Dummy >
int Letters_< Dummy >::array[26]    =
{
    letA, letB, letC, letD, letE, letF, letG, letH,
    letI, letJ, letK, letL, letM, letN, letO, letP, letQ, letR, letS,
    letT, letU, letV, letW, letX, letY, letZ
};

static int (&lettersArr)[26]    = Letters_<void>::array;

int main()
{
    using namespace std;
    for( int i = 0;  i < 26;  ++i )
    {
        cout << char( lettersArr[i] );
    }
    cout << endl;
}

Cheers & hth.,

欢呼声& hth。

#5


0  

You can do it this way:

你可以这样做:

in header

在头

extern int lettersArr[26];

in .cpp

. cpp中

int lettersArr[26] = { letA, letB, letC, letD, letE, letF, letG, letH,
        letI, letJ, letK, letL, letM, letN, letO, letP, letQ, letR, letS,
        letT, letU, letV, letW, letX, letY, letZ };

#6


0  

Here's a snippet from one of my header files (the implementation .cpp file accesses the array): (Use dummy::messages outside of the dummy namespace to access the array.)

下面是我的头文件中的一个片段(实现.cpp文件访问数组):(使用虚拟的::在虚拟名称空间之外的消息来访问数组)。

<pre>
    namespace dummy {

const static string messages[] = {
        "Unix does not echo the password field. Why do you think this is?",
        "The firewall blocks external access to ouranos. You need to login to helios and ssh or sftp to ouranos",
        "You need to experience of the command line. Not all systems have a gui.",
};

class Message {
public:
    Message();
    virtual ~Message();

    string getMessage();
    string getMessage( int index );
    int getRandomNumber();
};

} /* namespace dummy */
</pre>

#7


-2  

try:

试一试:

lettersArr = { 1, 2, 3, 4 }

#1


22  

Add extern to the declaration in the header file.

将extern添加到头文件中的声明。

extern int lettersArr[26];

(Also, unless you plan to change the array, consider also adding const.)

(另外,除非您打算更改数组,否则还可以考虑添加const。)

The definition must have a type. Add int (or const int):

定义必须有一个类型。增加int(或const int):

int lettersArr[26] = { letA, /*...*/ };

#2


4  

Header:

标题:

extern int lettersArr[];

Source at the global scope:

全球范围的来源:

int lettersArr[26] = { letA, letB, letC, letD, letE, letF, letG, letH,
    letI, letJ, letK, letL, letM, letN, letO, letP, letQ, letR, letS,
    letT, letU, letV, letW, letX, letY, letZ };

or if you really want to do it in a function:

或者如果你真的想用函数来做:

Source at global scope:

源在全球范围:

int lettersArr[26];

Source in function:

源的功能:

int localLettersArr[26] = { letA, letB, letC, letD, letE, letF, letG, letH,
    letI, letJ, letK, letL, letM, letN, letO, letP, letQ, letR, letS,
    letT, letU, letV, letW, letX, letY, letZ };

memcpy (lettersArr, localLettersArr, sizeof (localLettersArr));

#3


2  

Change what you have in the header to:

将标题中的内容更改为:

extern int lettersArr[26];

so that it will become a declaration, not a definition.

因此它将成为一个声明,而不是定义。

#4


1  

Other have described how the array initialization can be moved to an implementation file, which is not exactly answering your question, but is a workaround that's useful to know.

其他人描述了如何将数组初始化移动到实现文件中,这并不能完全回答您的问题,但这是一个有用的解决方案。

I just want to declare an array in my C++ header file

我只想在c++头文件中声明一个数组

If you really want to have the array all in your header file, including having the initialization in your header file, then you can

如果您真的希望在头文件中包含所有的数组,包括在头文件中进行初始化,那么您可以。

  • give it internal linkage by using static, or

    通过使用静态,或者,给它内部链接。

  • use a local static in an inline function (which supports effectively external linkage), or

    在内联函数中使用本地静态(它支持有效的外部链接),或者

  • use a little template trick (also supports external linkage).

    使用一个小模板技巧(也支持外部链接)。

The last two solutions are workarounds for the lack of "inline" data in C++. That is, the ability to define the same namespace scope object in more than one translation unit. You have that for functions, via inline, but unfortunately not for objects: without employing some workaround the linker will just protest about multiple definitions.

最后两个解决方案是解决c++中缺少“内联”数据的问题。即在多个转换单元中定义相同名称空间范围对象的能力。对于函数,可以通过内联实现,但不幸的是对于对象:如果不使用一些变通方法,链接器只会*多个定义。

Internal linkage

This is generally not a good solution. It creates one array in each translation unit where the header is included. But it's preferable for relatively small const objects because it's so simple:

这通常不是一个好的解决方案。它在包含头的每个转换单元中创建一个数组。但对于相对较小的const对象,它更可取,因为它非常简单:

#include <stddef.h>
#include <iostream>

int const   letA    = 'A';
int const   letB    = 'B';
int const   letC    = 'C';
int const   letD    = 'D';
int const   letE    = 'E';
int const   letF    = 'F';
int const   letG    = 'G';
int const   letH    = 'H';
int const   letI    = 'I';
int const   letJ    = 'J';
int const   letK    = 'K';
int const   letL    = 'L';
int const   letM    = 'M';
int const   letN    = 'N';
int const   letO    = 'O';
int const   letP    = 'P';
int const   letQ    = 'Q';
int const   letR    = 'R';
int const   letS    = 'S';
int const   letT    = 'T';
int const   letU    = 'U';
int const   letV    = 'V';
int const   letW    = 'W';
int const   letX    = 'X';
int const   letY    = 'Y';
int const   letZ    = 'Z';

static int lettersArr[26]   =
{
    letA, letB, letC, letD, letE, letF, letG, letH,
    letI, letJ, letK, letL, letM, letN, letO, letP, letQ, letR, letS,
    letT, letU, letV, letW, letX, letY, letZ
};

int main()
{
    using namespace std;
    for( int i = 0;  i < 26;  ++i )
    {
        cout << char( lettersArr[i] );
    }
    cout << endl;
}

Local static in inline function

This is probably the generally "best" solution, to use when there is no overriding reason for choosing one of the other solutions. One nice thing is that it's easy to provide dynamic initialization. Here I've just assumed that you will never store 0 in the array (add some extra checking logic if that assumption doesn't hold):

这可能是通常的“最佳”解决方案,当没有压倒一切的理由选择其他解决方案时使用。一件好事是提供动态初始化很容易。这里我假设您永远不会在数组中存储0(如果这个假设不成立,添加一些额外的检查逻辑):

#include <stddef.h>
#include <iostream>

template< class Type, int n >
int countOf( Type (&)[n] ) { return n; }

typedef int LettersArray[26];

inline LettersArray& lettersArrayRef()
{
    static LettersArray theArray;

    if( theArray[0] == 0 )
    {
        // Assuming normal ASCII-based character set with contiguous alpha.
        for( int i = 0;  i < countOf( theArray );  ++i )
        {
            theArray[i] = i + 'A';
        }
    }
    return theArray;
}

static LettersArray&    lettersArr  = lettersArrayRef();

int main()
{
    using namespace std;
    for( int i = 0;  i < 26;  ++i )
    {
        cout << char( lettersArr[i] );
    }
    cout << endl;
}

Template trick

The template trick works because the standard's ODR, One Definition Rule, makes a special exemption for templates:

模板技巧之所以有效,是因为标准的ODR(定义规则之一)对模板进行了特殊的豁免:

#include <stddef.h>
#include <iostream>

int const   letA    = 'A';
int const   letB    = 'B';
int const   letC    = 'C';
int const   letD    = 'D';
int const   letE    = 'E';
int const   letF    = 'F';
int const   letG    = 'G';
int const   letH    = 'H';
int const   letI    = 'I';
int const   letJ    = 'J';
int const   letK    = 'K';
int const   letL    = 'L';
int const   letM    = 'M';
int const   letN    = 'N';
int const   letO    = 'O';
int const   letP    = 'P';
int const   letQ    = 'Q';
int const   letR    = 'R';
int const   letS    = 'S';
int const   letT    = 'T';
int const   letU    = 'U';
int const   letV    = 'V';
int const   letW    = 'W';
int const   letX    = 'X';
int const   letY    = 'Y';
int const   letZ    = 'Z';

template< class Dummy >
struct Letters_
{
    static int  array[26];
};

template< class Dummy >
int Letters_< Dummy >::array[26]    =
{
    letA, letB, letC, letD, letE, letF, letG, letH,
    letI, letJ, letK, letL, letM, letN, letO, letP, letQ, letR, letS,
    letT, letU, letV, letW, letX, letY, letZ
};

static int (&lettersArr)[26]    = Letters_<void>::array;

int main()
{
    using namespace std;
    for( int i = 0;  i < 26;  ++i )
    {
        cout << char( lettersArr[i] );
    }
    cout << endl;
}

Cheers & hth.,

欢呼声& hth。

#5


0  

You can do it this way:

你可以这样做:

in header

在头

extern int lettersArr[26];

in .cpp

. cpp中

int lettersArr[26] = { letA, letB, letC, letD, letE, letF, letG, letH,
        letI, letJ, letK, letL, letM, letN, letO, letP, letQ, letR, letS,
        letT, letU, letV, letW, letX, letY, letZ };

#6


0  

Here's a snippet from one of my header files (the implementation .cpp file accesses the array): (Use dummy::messages outside of the dummy namespace to access the array.)

下面是我的头文件中的一个片段(实现.cpp文件访问数组):(使用虚拟的::在虚拟名称空间之外的消息来访问数组)。

<pre>
    namespace dummy {

const static string messages[] = {
        "Unix does not echo the password field. Why do you think this is?",
        "The firewall blocks external access to ouranos. You need to login to helios and ssh or sftp to ouranos",
        "You need to experience of the command line. Not all systems have a gui.",
};

class Message {
public:
    Message();
    virtual ~Message();

    string getMessage();
    string getMessage( int index );
    int getRandomNumber();
};

} /* namespace dummy */
</pre>

#7


-2  

try:

试一试:

lettersArr = { 1, 2, 3, 4 }