C++ C/C++;:从a.h导出变量
在C/C++中,我想从main.cpp使用一个即用变量(mTab),即:C++ C/C++;:从a.h导出变量,c++,C++,在C/C++中,我想从main.cpp使用一个即用变量(mTab),即: 在lib.h中声明并初始化 在lib.cpp中实现 我做不到,怎么了?似乎typedef被忽略了,我不明白为什么 注: 由于lib.h的每个用户的mTab必须相同,因此我添加了static关键字 由于静态变量必须始终初始化(以避免意外行为),我在lib.h中初始化了mTab 当我在lib.cpp中移动mTab初始化时:编译是KO 当我在lib.cpp和中移动mTab声明和初始化时,在main.cpp中使用“extern”:
#include "lib.h"
void m1 ( unsigned int const iDataSize, int * const iopData ) { return; }
void m2 ( unsigned int const iDataSize, int * const iopData ) { return; }
pF mTab[2] = {&m1, &m2};
lib.h
main.cpp
#include "lib.h"
#include <stddef.h> // NULL
int main ()
{
(*mTab[0]) ( 0, NULL );
(*mTab[1]) ( 0, NULL );
return 0;
}
控制台:
~>make
gcc -I. -c lib.cpp -o lib.o
In file included from lib.cpp:1:0:
lib.h:7:1: error: ‘mTab’ does not name a type
lib.h:8:1: error: ‘mTab’ does not name a type
make: *** [all] Error 1
在全局命名空间中不能这样做。尝试在一个CPP中定义它,并在标题中将其作为“extern”
静态
在这个上下文中是指其他内容<代码>静态表示变量具有内部链接。这意味着每个编译单元将存在一个单独的变量。您想在标题中使用extern
此外,请为您的include guard选择除\uuuuu lib\uuuuu
之外的其他符号。包含双下划线的标识符保留供实现使用
最后,正如ahoka所指出的,您不能将代码放在名称空间范围内。这只在函数中有效。这样做:
lib.h
lib.cpp
#include "lib.h"
void m1 ( unsigned int const iDataSize, int * const iopData ) { return; }
void m2 ( unsigned int const iDataSize, int * const iopData ) { return; }
pF mTab[2] = {&m1, &m2};
首先,只在共享头文件中放置声明,而不是对象或函数的定义。对于mTab,请在lib.h中使用:
extern pF mTab[2];
其次,在一个且仅一个源文件中定义对象。将其放在lib.cpp中:
pf mTab[2] = { m1, m2 };
第三,mTab[0]=&m1代码>不是mTab的初始化。它可能是一个赋值语句,但它位于错误的位置,因为您不能在文件范围中使用赋值语句。上面显示了初始化mTab的正确方法。(赋值不同于初始化。赋值是可执行语句,必须在函数体内。初始化是对象创建的一部分,可能发生在程序的主要执行之前。)
第四,static
不会使每个用户的对象都相同。它有两种效果,可能因使用位置而异。在文件范围中使用时,表示标识符具有内部链接,这意味着标识符仅引用当前编译中的对象;它与其他编译中的同一标识符没有外部链接。所以它实际上意味着与你所写的相反;这意味着每个源文件都有自己的mTab
,而不是它们共享一个mTab
。(staticstatic
的第二个效果是给对象一个静态存储持续时间,因此它的生命周期是程序的整个执行过程。但是,这在文件范围内没有效果,因为在文件范围内声明的对象默认具有静态存储持续时间。)在声明中,您甚至可以省略数组大小,将其留在mTab[]外部的。当然,告诉这个数组的用户最大大小会很有用,这样你就不会越界了;你应该使用其他资源进行正常学习。堆栈溢出更好地用于那些已经基本上学会了一门学科的人感到困惑的问题。
pF mTab[2] = {&m1, &m2};
extern pF mTab[2];
pf mTab[2] = { m1, m2 };