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中的统一初始值设定项语法将
新建

即:

或者类似的。(注意使用placement
new
,我不是在空闲存储(也称为堆)上创建内存。还要注意的是,如果不是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中的统一初始值设定项语法将
新建

即:

或者类似的东西。(注意使用placement
new
,我不是在空闲存储(也称为堆)上创建内存。还要注意,如果不是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
。你到底想实现什么?也许对代码的解释也会有所帮助。它是两个独立的源文件还是只有一个?嗯..将它移到函数之外