半循环定义(加上循环引用) [英] Semi-circular definitions (plus circular references)

查看:140
本文介绍了半循环定义(加上循环引用)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有一种优雅的方式来处理半圆定义?


半圆定义:

A {B};

B {* A};

循环参考:

A {* B};

B {* A};


当有更多的半圆形定义和

循环引用时会出现问题。


请考虑以下示例代码:


--- inc1.h ---

#ifndef INC1_INCLUDE

#define INC1_INCLUDE


typedef struct _struc2

{

struct _struc1 * s1;

} struc2;

typedef struct _struc3

{

struct _struc1 * s1;

} struc3;


typedef struct _struc1

{

struct _struc2 s2;

struct _struc3 s3;

} struc1;


typedef struct _struc4

{

struct _struc1 s1;

} struc4;


#endif


--- test.cpp ---


#include" inc1.h"


int main()

{

struc1 s1;

s1.s2;


返回1;

}


------


前面的代码显然是正确的。

现在我想将包含文件分成两个独立的文件。

原始包含文件包含4个定义:

A

B

C

D

当拆分原来包括

文件无法通过重新附加2个包含文件获得时出现问题。

例如,inc1.h可以包含A和D,以及inc2.h B和C.


--- inc1.h ---

#ifndef INC1_INCLUDE

#define INC1_INCLUDE


#include" inc2.h"


typedef struct _struc2

{

struct _struc1 * s1;

} struc2;


typedef struct _struc4

{

struct _struc1 s1;

} struc4;


#endif


--- inc2.h ---

#ifndef INC2_INCLUDE

#define INC2_INCLUDE


#include" inc1.h"


typedef struct _struc3

{

struct _struc1 * s1;

} struc3;


typedef struct _struc1 < br $>
{

struct _struc2 s2;

struct _struc3 s3;

} struc1;


#endif


-------


有人肯定这种情况是组织不良的指标,但是我不同意,然后我不寻求一个明显的解决方法,而是一个解决方案

*原始*问题。

是的,我可以使用指针而不是结构本身,但我没有想要使用不需要的间接。

我甚至可以使用虚拟结构,但该解决方案非常不优雅。


是否有特定的指令指示编译器分析

th在放弃之前整个文件?


有没有比使用一堆#if ... [...]更好的解决方案..#endif? :)


谢谢,Kiuhnm

Is there an elegant way to deal with semi-circular definitions?

Semi-circular definition:
A { B };
B { *A };
Circular reference:
A { *B };
B { *A };

The problems arise when there are more semi-circular definitions and
circular references.

Consider the following sample code:

--- inc1.h ---
#ifndef INC1_INCLUDE
#define INC1_INCLUDE

typedef struct _struc2
{
struct _struc1 *s1;
} struc2;
typedef struct _struc3
{
struct _struc1 *s1;
} struc3;

typedef struct _struc1
{
struct _struc2 s2;
struct _struc3 s3;
} struc1;

typedef struct _struc4
{
struct _struc1 s1;
} struc4;

#endif

--- test.cpp ---

#include "inc1.h"

int main()
{
struc1 s1;
s1.s2;

return 1;
}

------

The previous code is obviously correct.
Now I want to split the include file in two separated files.
The original include file contains 4 definitions:
A
B
C
D
The problem arises when the splitting is such that the original include
file cannot be obtained by reattaching the 2 include files.
For Example, inc1.h could contain A and D, and inc2.h B and C.

--- inc1.h ---
#ifndef INC1_INCLUDE
#define INC1_INCLUDE

#include "inc2.h"

typedef struct _struc2
{
struct _struc1 *s1;
} struc2;

typedef struct _struc4
{
struct _struc1 s1;
} struc4;

#endif

--- inc2.h ---
#ifndef INC2_INCLUDE
#define INC2_INCLUDE

#include "inc1.h"

typedef struct _struc3
{
struct _struc1 *s1;
} struc3;

typedef struct _struc1
{
struct _struc2 s2;
struct _struc3 s3;
} struc1;

#endif

-------

Someone affirms that this situation is index of bad organization, but I
disagree, then I do not seek an obvious workaround, but a solution to
the *original* problem.
Yes, I could use a pointer instead of the struct itself, but I do not
want to use an unneeded indirection.
I could even use a dummy structure but that solution is very inelegant.

Is there a particular directive which instructs the compiler to analyze
the entire file before giving up?

Is there a better solution than using a bunch of #if..[...]..#endif? :)

Thanks, Kiuhnm

推荐答案

Kiuhnm写道:
是有一种优雅的方式来处理半圆定义吗?
Is there an elegant way to deal with semi-circular definitions?




你只需稍微重组一下。这是我的解决方案,似乎是工作的b $ b:


inc1.h:

------- -


#ifndef INC1_INCLUDE

#define INC1_INCLUDE


typedef struct _struc2

{

struct _struc1 * s1;

} struc2;

#include" inc2.h"

typedef struct _struc4

{

struct _struc1 s1;

} struc4;

#endif


----------------

inc2.h:

--- ------------- #include" inc1.h"

#ifndef INC2_INCLUDE

#define INC2_INCLUDE


typedef struct _struc3

{

struct _struc1 * s1;

} struc3;



typedef struct _struc1

{

struct _struc2 s2;

struct _struc3 s3;

} struc1;


#endif

--------


为我编译干净。


Jon

- -

学习使用Linux汇编语言进行编程
http://www.cafeshops.com/bartlettpublish.8640017


Jonathan Bartlett写道:
Jonathan Bartlett wrote:
Kiuhnm写道:
Kiuhnm wrote:
有没有一种优雅的方式来处理半圆定义?
Is there an elegant way to deal with semi-circular definitions?



你只需稍微重组一下。这是我的解决方案似乎可以工作:



You just need to restructure it a bit. Here''s my solution which seems
to work:



[cut]


你重新组合原始文件!

总是可以的吗?

不幸的是,没有。


--- inc1.h ---

s1 {s3}

s2 {s4}

--- inc2.h ---

s3 {s2}
s4 {}

--------------


让a< B"表示a必须出现在b之前。


s3< s1,

s4< s2

s2< s3


=>


s4< s2< s3< s1


那是'唯一正确的安排。


通过对每个包含文件中的结构进行部分重新排序,我们得到:

--- inc1.h ---

s2 {s4}

s1 {s3}

--- inc2.h ---

s4 {}

s3 {s2}

------------- -


s2 s1

s4 s3


如何在不分割任何文件的情况下获得该安排?

为什么编译器如此愚蠢?

编译器可以简单地执行第一遍并编译

表所有结构的大小然后在

连续传递中使用该表。


也许预处理器的文档可以帮助...


无论如何,谢谢你!


Kiuhnm


[cut]

You recomposed the original file!
Is it always possible?
No, unfortunately.

--- inc1.h ---
s1 {s3}
s2 {s4}
--- inc2.h ---
s3 {s2}
s4 {}
--------------

Let "a < b" mean "a must appear before b".

s3 < s1,
s4 < s2
s2 < s3

=>

s4 < s2 < s3 < s1

then that''s the only correct arrangement.

By partially reordering the structures in each include file, we obtain:
--- inc1.h ---
s2 {s4}
s1 {s3}
--- inc2.h ---
s4 {}
s3 {s2}
--------------

s2 s1
s4 s3

How can we obtain that arrangement without splitting any file?
Why are the compilers so stupid?
The compiler could simply perform a first pass and compile a table of
the sizes of all the structures and then use that table in the
successive passes.

Perhaps the documentation of the preprocessor could help...

Thank you anyway!

Kiuhnm


Kiuhnm写道:
你重组了原始文件!
它总是可能吗?
不,不幸的是。
You recomposed the original file!
Is it always possible?
No, unfortunately.




是的,*总是*可以重新排列数据结构的方式

声明,以便在需要之前声明实体。它可能需要在每个数据结构中声明每个数据结构,但它始终是可能的。


考虑会发生什么当声明一个真正的循环依赖时:


struct A {B b};

struct B(A a};


这意味着B包含A的副本,其中包括B的副本,

,其中包括A的副本,无限制。此结构具有无限大小

并且无法实例化。


换句话说,为了使数据结构具有有限的大小,其

组合图必须没有因此,所有有限数据结构

都可以通过一系列声明来描述,而不是前向依赖。


有时候不可能如果在一个或多个头文件中声明了多个数据结构,则正确声明数据结构。

在这种情况下你的问题不在于语言定义或者t他是b $ b编译器,但是模块的组织方式。


-dr



Yes, it is *always* possible to rearrange the way data structures are
declared so that entities are declared before they are needed. It may
entail declaring each data structure in its own header file, but it is
always possible.

Consider what happens when a truly circular dependency is declared:

struct A { B b };
struct B ( A a };

This implies that B includes a copy of A, which includes a copy of B,
which includes a copy of A, ad infinitum. This struct has infinite size
and is not possible to instantiate.

In other words, in order for a data structure to have finite size, its
composition graph must have no loops. Thus, all finite data structures
can be described by a sequence of declarations with no "forward dependency".

Sometimes it is not possible to properly declare data structures if
multiple data structures are declared within one or more header files.
Your problem in this case in not with the language definition or the
compiler, but with the way that your modules are organized.

-dr


这篇关于半循环定义(加上循环引用)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆