单独文件中的结构如何相互引用?

win*_*412 2 rust

使用相互引用的结构在单个文件中很常见,但是当我将结构分成两个文件时,我收到错误.

mod_1.rs

mod mod_2;
use mod_2::Haha;

pub struct Hehe {
    obj: Haha,
}

fn main() {
    Hehe(Haha);
}
Run Code Online (Sandbox Code Playgroud)

mod_2.rs

mod mod_1;
use mod_1::Hehe;

pub struct Haha {
    obj: Hehe,
}

fn main() {
    Haha(Hehe);
}
Run Code Online (Sandbox Code Playgroud)

这将产生错误.编译时mod_1.rs:

error: cannot declare a new module at this location
 --> mod_2.rs:1:5
  |
1 | mod mod_1;
  |     ^^^^^
  |
note: maybe move this module `mod_2` to its own directory via `mod_2/mod.rs`
 --> mod_2.rs:1:5
  |
1 | mod mod_1;
  |     ^^^^^
note: ... or maybe `use` the module `mod_1` instead of possibly redeclaring it
 --> mod_2.rs:1:5
  |
1 | mod mod_1;
  |     ^^^^^
Run Code Online (Sandbox Code Playgroud)

编译时mod_2.rs:

error: cannot declare a new module at this location
 --> mod_1.rs:1:5
  |
1 | mod mod_2;
  |     ^^^^^
  |
note: maybe move this module `mod_1` to its own directory via `mod_1/mod.rs`
 --> mod_1.rs:1:5
  |
1 | mod mod_2;
  |     ^^^^^
note: ... or maybe `use` the module `mod_2` instead of possibly redeclaring it
 --> mod_1.rs:1:5
  |
1 | mod mod_2;
  |     ^^^^^
Run Code Online (Sandbox Code Playgroud)

mod_1.rs我使用的东西从mod_2.rsmod_2.rs,我用mod_1.rs的东西,所以我想找到一种方法来摆脱周期参考模块的问题.

试图让Rust加载文件是一个类似但不同的问题.

Luk*_*odt 7

这是对Rust模块系统的常见误解.基本上,有两个步骤:

  1. 您必须构建模块树.这意味着此模块树中没有循环,并且节点之间存在明确的父子关系.这一步只是告诉Rust要加载哪些文件,与不同模块中某些符号的使用无关.

  2. 您现在可以通过其路径(每个模块,最终符号名被分离出的基准在你的模块树中的每个符号::,例如std::io::read).为了避免每次都写入完整路径,您可以使用use声明通过简单名称引用特定符号.

您可以在Rust书籍章节中阅读更多内容.

再次,为了避免混淆:为了使用符号从一个模块,你并不一定要写出mod my_module;你的模块!对于项目中的每个非根模块只有一个在整个项目线说mod said_module;(根模块没有在所有这样的线).只有一次!


关于你的例子:你首先编译mod_1.rs通过rustc mod_1.rs.这意味着这mod_1是您案例中的根模块.如上所述,根模块根本不需要通过声明mod,但是所有其他模块只需要声明一次.这意味着mod mod_2;mod_1.rs是完全正确的,但是mod mod_1;mod_2.rs不正确.编译器甚至建议做正确的事情:

note: ... or maybe `use` the module `mod_2` instead of possibly redeclaring it
Run Code Online (Sandbox Code Playgroud)

您已经在使用use它,因此您可以删除该行mod mod_1;并解决此错误.

但是,我认为你仍然在思考模块系统.如上所述,您首先需要设计一个或多或少固定的模块树,这意味着您有一个固定的根模块.无论你传递给什么rustc是根模块,使用不同的模块作为根模块是没有意义的.在您的项目中应该有一个固定的根模块.这可以mod_1如上所述.但是,lib为图书馆和main可执行文件调用它通常更为惯用.

再说一次:首先,在一张纸上绘制模块树.暂时考虑这个问题,然后你可以mod适当地创建文件和声明.


最后一点:即使在修复模块系统时,您的示例也不起作用,因为Haha并且Hehe是具有无限大小的类型.结构的字段直接放入结构的内存布局中(不像Java那样装箱!).因此,除了手动添加间接层(如装箱字段)之外,您不能在结构定义中使用循环.请阅读有关此问题的优秀解释.

  • @ wind2412你几乎得到了它 - 需要一个单独的"root"模块,其中包含`mod_1`和`mod_2`作为其子项.我建议创建一个`lib.rs`,除了声明`mod mod_1;`和`mod mod_2;`之外什么都不做. (2认同)