从定义中拆分声明 我真的想使用D,因为它的语言结构做了很多我比C++更关心的事情,但是几乎强制GC(),稍微少了一些强大的操作符重载(除了 opDestabr>代码> opDistabs/Copy>是性感的),下面的问题有点让我厌烦。

从定义中拆分声明 我真的想使用D,因为它的语言结构做了很多我比C++更关心的事情,但是几乎强制GC(),稍微少了一些强大的操作符重载(除了 opDestabr>代码> opDistabs/Copy>是性感的),下面的问题有点让我厌烦。,d,D,在D中是否可以从定义中拆分方法声明?如果是,怎么做?若否,原因为何 “how”的激励示例:在二进制对象旁边提供一个接口函数的小头文件,如C头文件和库,以便将实现隐藏在用户代码编写者的视线之外。首选项:不取决于用户代码是否已破解垃圾收集器或只是在没有druntime的情况下编译(见注释)。您可以使用extern声明函数,而无需指定其实现,例如: extern(D): void foo(string name); 然后简单地提供一个带有链接实现的对象文件/归档。请注意,模块名称是函数损坏名称的一部

在D中是否可以从定义中拆分方法声明?如果是,怎么做?若否,原因为何


“how”的激励示例:在二进制对象旁边提供一个接口函数的小头文件,如C头文件和库,以便将实现隐藏在用户代码编写者的视线之外。首选项:不取决于用户代码是否已破解垃圾收集器或只是在没有druntime的情况下编译(见注释)。

您可以使用
extern
声明函数,而无需指定其实现,例如:

extern(D):
void foo(string name);

然后简单地提供一个带有链接实现的对象文件/归档。请注意,模块名称是函数损坏名称的一部分,因此头文件需要与已编译模块相同的模块名称,或者您可以使用
extern(C)
禁用损坏(排除重载并使用C调用约定)。

如果我编写这样的D文件:并且您使用dmd-C编译,你会发现它没有错误;这是一个有效的D文件。该语言允许您编写无需实现的函数原型

di文件就是这样,它只是有一个不同的文件名

然后给定main:如果您编译dmd main,当它看到“import iface.test;”时,它将自动搜索iface/test.d,找到该.d文件,或者如果您重命名该文件但名称相同,则找到.di,并获取接口定义

dmd main将因链接器错误而失败,因此我们需要实现它:注意:impl不会导入模块,因此它从不检查其他文件。保持.di和.d文件的同步是其中一个棘手的部分,除非您自动生成接口文件,因为未定义的方法会导致链接器错误,但方法的顺序很重要:它必须匹配,如果有公共变量,变量列表也必须匹配。否则,使用代码和实现代码将无法在类的布局上达成一致

再次,它不自动检查,实现文件根本不看“头”文件,所以这是一个与C++的主要区别,在这里你写了头文件一次,然后在使用程序和实现文件中使用它。 您会注意到,实现文件还列出了类等。d不支持<代码>无效MyCype::Additer(int A){} /COD>语法C++必须在类之外写入方法。 据我所知,无法强制实现文件查找标头,如果将两者都放在命令行上,则会得到:“错误:文件iface/test.d中的module iface.test与文件impl.d中的另一个module test冲突”


建议使用.di文件的方式是使用dmd-H自动生成它们。这将读取完整的实现文件并去掉函数体,只留下定义。当他们说这是编译器的一项功能时,这一部分可能是关键所在,.di文件是有效的、标准的D文件,但通过一个编译器选项生成,该选项不一定是其他编译器的一部分。

Adam已经解释了一切。我将尝试添加一个额外的示例:

假设您正在开发一个名为mylib的库,它有函数foo()和bar()。您的代码和库测试应用程序在开始时可能如下所示:

mylib.d-接口文件

module mylib;

void foo();
void bar();
module mylib;

import std.stdio;

void foo() {
  writeln("foo()");
}

void bar() {
  writeln("bar()");
}
mylib\u impl.d-定义见此处

module mylib;

void foo();
void bar();
module mylib;

import std.stdio;

void foo() {
  writeln("foo()");
}

void bar() {
  writeln("bar()");
}
mylib_test.d-测试应用程序

// To compile: dmd mylib_impl.d mylib_test.d
// NOTE: we do not compile the "interface" file mylib.d !!
module mylib_test;

import mylib;

int main() {
  foo();
  bar();

  return 0;
}

现在不难理解,我们拥有.di文件纯粹是为了方便和清晰。如果我们决定使用接口文件,我们会将mylib.d重命名为mylib.di,将mylib_impl.d重命名为mylib.d。mylib_test.d将保持不变。

阅读有关d接口文件的内容。@DejanLekic我只看到编译器文档部分中指定的d接口文件。它是一个由编译器编译的东西还是一种语言的东西?编辑:布拉格,请进一步阅读。它们不是语言的一部分。是否有一种解决方案是该语言的一部分?D接口文件只是使用同一D语言的不同部分。(事实上,dmd编译器并不关心扩展名是.d还是.di,它们的工作方式都是一样的。)@AdamD.Ruppe A'light-但是你能澄清一下下面的引文吗(来自):“D接口文件与C++头文件有一些相似的相似之处。但是它们不是以C++头文件的方式所需要的,它们不是D语言的一部分。它们是编译器的一个特性,并且只作为构建过程的优化。“@AdamD.Ruppe我的意思是,说清楚点,我不是一个纯粹主义者,我不会说.di文件不是核心语言定义的一部分是一种关闭。我只是想知道它们是怎么回事。FWIW,.di文件只是这个惯例的自动化。@BCS,因此它最终对我有指导意义。谢谢你。包只是一个目录。它应该在没有更改的情况下工作。
dmd main
查看错误,并
dmd main.d impl.d
查看它是否成功运行。将这两个文件下载到您自己的文件夹中。