1

我在函数中使用前向声明时遇到问题。通常在全局范围内,我们可以使用使用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

我该如何解决这个位问题?

4

3 回答 3

1

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

于 2012-12-11T15:32:57.760 回答
0

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

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

似乎您前向声明的唯一原因是您可以{ }在结构上使用初始化语法。比使用 hack 更好地分配成员。

如果你必须,那么你可以使用void *,但对于粗心的人来说,这会撒上陷阱。

于 2012-12-11T15:40:28.980 回答
0

extern ChIdRec Evn; does not do what you think it does when put inside a function.

A variable that is extern is a global variable. Even if you declare it inside a function. This lets you say you are using an extern global variable half way through a function body, right adjacent to where you access it. But it does mean you cannot "forward declare" a local variable.

Now, in theory you could create your struct at one spot without constructing it, do some more work, then in-place new with the uniform initializer syntax in C++11.

ie:

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

or something like that. (Note the use of placement new, I am not creating memory on the free store (aka heap). Also note that double-construction of ChIdRec is dangerous if it is not POD -- if ChIdRec contained a std::string, I would expect the above to leak or crash, for example.

A slightly more ridiculous, yet correct, method:

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

which could be dressed up in fancy stuff to make it exception safe and less awkward. Basically, a delayed-construction abstraction would make this marginally less ridiculous.

于 2012-12-11T15:49:36.053 回答