函数中的前向声明

时间:2012-12-11 15:16:15

标签: 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 = {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}; 
}

但现在我们遇到了错误 - error C2086: 'ChIdRec Evn' : redefinition。 我们可以删除Evn的第一个声明,但我们会有另一个错误 - error C2065: 'Evn' : undeclared identifier

我如何解决这个问题?

3 个答案:

答案 0 :(得分:1)

不要重复函数内部类型的定义。特别是typedef使得这是一个新的标识符,即使它与全局标识符具有相同的名称和含义。

答案 1 :(得分:0)

extern表示变量在另一个代码单元中定义,由链接器解析。如果结构是在本地函数中定义的,那么我看不出你如何期望它extern

问题是你有一个外部变量,然后你试图将同一个变量声明为local。编译器说“下定决心,是外部还是本地?”。

似乎你的前向声明的唯一原因是你可以在结构上使用{ }初始化语法。最好按成员分配成员而不是使用黑客。

如果你必须那么你就可以使用void *,但是那些不知不觉中有陷阱。

答案 2 :(得分:0)

extern ChIdRec Evn;在放入函数时不会按照您的想法执行。

extern的变量是全局变量。即使你在一个函数内声明它。这可以让您说您在函数体的中间使用extern全局变量,在您访问它的位置附近。但它确实意味着你不能“转发声明”一个局部变量。

现在,理论上你可以在一个地方创建你的struct而不构建它,做更多的工作,然后使用C ++ 11中的统一初始化语法就地new

即:

ChIdRec Evn;
IdN Arr[] = {(IdN)&Evn};
new(&Evn)ChIdRec{8, Arr}; 

或类似的东西。 (注意使用placement new,我没有在免费商店(也就是堆)上创建内存。另请注意,ChIdRec的双重构造如果不是POD则是危险的 - 如果包含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

可以装扮成花哨的东西,使它异常安全,不那么尴尬。基本上,延迟构造抽象会使这一点略微荒谬。