C++ 函数中的转发声明
我在函数中使用前向声明时遇到问题。通常在全局范围内,我们可以使用未定义变量的地址,该变量使用C++ 函数中的转发声明,c++,c,C++,C,我在函数中使用前向声明时遇到问题。通常在全局范围内,我们可以使用未定义变量的地址,该变量使用extern关键字声明。看看这个简单的例子 typedef struct Id { int a; } xIdRec; typedef xIdRec* IdN; typedef struct ChId{ int a; IdN* b; } ChIdRec; extern ChIdRec Evn; IdN Arr[] = {(IdN)&Evn}; ChIdRec Evn
extern
关键字声明。看看这个简单的例子
typedef struct Id {
int a;
} xIdRec;
typedef xIdRec* IdN;
typedef struct ChId{
int a;
IdN* b;
} ChIdRec;
extern ChIdRec Evn;
IdN Arr[] = {(IdN)&Evn};
ChIdRec Evn = {8, Arr};
但是我如何在函数定义期间使用这些代码呢?我们可以试着这样使用它
void F (){
typedef struct Id {
int a;
} xIdRec;
typedef xIdRec* IdN;
typedef struct ChId{
int a;
IdN* b;
} ChIdRec;
extern ChIdRec Evn;
IdN Arr[] = {(IdN)&Evn};
ChIdRec Evn = {8, Arr};
}
但现在我们有一个错误-错误C2086:“ChIdRec Evn”:重新定义。
我们可以删除Evn
的第一个声明,但会出现另一个错误-错误C2065:“Evn”:未声明的标识符
如何解决此位问题?不要重复函数中类型的定义。尤其是typedef
使得这是一个新的标识符,即使它与全局标识符具有相同的名称和含义 不要重复函数中类型的定义。尤其是typedef
使得这是一个新的标识符,即使它与全局标识符具有相同的名称和含义 extern
表示变量定义在另一个代码单元中,由链接器解析。如果该结构是在本地函数中定义的,那么我看不出您如何期望它也是extern
问题是您有一个外部变量,然后您试图将同一个变量声明为局部变量。编译器说“下定决心,它是外部的还是本地的?”
似乎转发声明的唯一原因是您可以在结构上使用{}
初始化语法。一个成员一个成员地分配比使用黑客更好
如果必须这样做,则可以使用void*
,但对于粗心的人来说,这会撒上陷阱。extern
意味着变量是在另一个代码单元中定义的,由链接器解析。如果该结构是在本地函数中定义的,那么我看不出您如何期望它也是extern
问题是您有一个外部变量,然后您试图将同一个变量声明为局部变量。编译器说“下定决心,它是外部的还是本地的?”
似乎转发声明的唯一原因是您可以在结构上使用{}
初始化语法。一个成员一个成员地分配比使用黑客更好
如果你必须这样做,那么你可以使用void*
,但对于不小心的人来说,这是一个陷阱。extern ChIdRec Evn代码>不做您认为它在函数中所做的事情
extern
的变量是全局变量。即使您在函数中声明它。这意味着您正在函数体中间使用一个extern
全局变量,它就在您访问它的位置附近。但这确实意味着不能“前向声明”局部变量
现在,从理论上讲,您可以在一个位置创建结构
,而无需构建它,再做一些工作,然后使用C++11中的统一初始值设定项语法将新建
即:
或者类似的。(注意使用placementnew
,我不是在空闲存储(也称为堆)上创建内存。还要注意的是,如果不是POD,ChIdRec
的双重结构是危险的——例如,如果ChIdRec包含std::string
,我预计上面的内容会泄漏或崩溃
一种稍微可笑但又正确的方法:
unsigned char EvnBuff[sizeof(ChIdRec)];
IdN Arr[] = {reinterpret_cast<IdN>(&EvnBuff[0])};
new(&EvnBuff[0])ChIdRec{8, Arr};
ChIdRec& Evn = *reinterpret_cast<ChIdRec*>(&EvnBuff[0]);
// ... code goes here
Evn->~ChIdRec (); // before leaving body of function, iff ChIdRec::~ChIdRec exists
无符号字符EvnBuff[sizeof(ChIdRec)];
IdN Arr[]={reinterpret_cast(&EvnBuff[0])};
新的(&EvnBuff[0])ChIdRec{8,Arr};
ChIdRec和Evn=*重新解释铸造(&EvnBuff[0]);
//…代码在这里
Evn->~ChIdRec();//在离开函数体之前,iff ChIdRec::~ChIdRec存在
基本上,一个延迟的构造抽象会使这稍微不那么荒谬。extern ChIdRec Evn;
不会做你认为它在函数中做的事情
extern
变量是全局变量。即使在函数中声明它。这意味着您在函数体的中间使用了一个extern
全局变量,就在您访问它的位置附近。但这意味着您不能“前向声明”局部变量
现在,从理论上讲,您可以在一个位置创建结构
,而无需构建它,再做一些工作,然后使用C++11中的统一初始值设定项语法将新建
即:
或者类似的东西。(注意使用placementnew
,我不是在空闲存储(也称为堆)上创建内存。还要注意,如果不是POD,则双重构造ChIdRec
是危险的——例如,如果ChIdRec包含std::string
,我预计上面的内容会泄漏或崩溃
一种稍微可笑但又正确的方法:
unsigned char EvnBuff[sizeof(ChIdRec)];
IdN Arr[] = {reinterpret_cast<IdN>(&EvnBuff[0])};
new(&EvnBuff[0])ChIdRec{8, Arr};
ChIdRec& Evn = *reinterpret_cast<ChIdRec*>(&EvnBuff[0]);
// ... code goes here
Evn->~ChIdRec (); // before leaving body of function, iff ChIdRec::~ChIdRec exists
无符号字符EvnBuff[sizeof(ChIdRec)];
IdN Arr[]={reinterpret_cast(&EvnBuff[0])};
新的(&EvnBuff[0])ChIdRec{8,Arr};
ChIdRec和Evn=*重新解释铸造(&EvnBuff[0]);
//…代码在这里
Evn->~ChIdRec();//在离开函数体之前,iff ChIdRec::~ChIdRec存在
基本上,一个延迟的构造抽象会使它稍微不那么荒谬。Umm..将它移到函数之外?struct ChIdRec
是一个局部结构,如何在函数之外实例化它F()
?为什么再次在本地声明extern ChIdRec Evn
?extern foo bar
只应出现一次,即在模块的标题中(如果有)这实现了foo-bar
。你到底想实现什么?也许对代码的解释也会有所帮助。它是两个独立的源文件还是只有一个?嗯..将它移到函数之外