当使用C++模块时,是否有必要将函数声明(.hpp文件)与其定义(.cpp文件)分开?

24

我习惯于编写没有模块的代码,其中头文件包含函数声明,例如:

// foo.h 
class Foo
{
    void bar();
};

对应的 .cpp 文件包含如下定义:

// foo.cpp
#include "foo.h"

void Foo::bar()
{
    // ...
}

据我所知,这样做是为了减少编译时间和减少依赖性。当模块被使用时,这仍然适用吗?把类的定义放在一个文件中,就像Java和C#那样,速度会不会一样快?如果是这样,那么在使用模块时是否需要同时使用.hpp.cpp文件呢?

你将如何引用一个函数?如果你 #include 了你的组合头文件和 .cpp 文件,你将会多次定义函数。 - Ant
我有同样的想法。我总是觉得在C++中分离声明和实现比它值得的麻烦多了。这主要是因为模板...这就是为什么许多现代通用C++库只有头文件。我认为模块是C++的一个巨大飞跃;终于将其与C遗产分开。 - rmccabe3701
4个回答

11

就我所知,根据当前模块提案,唯一的原因是为了处理循环接口依赖关系。

如果程序由多个模块组成,并且没有将函数声明与定义分开,那么所有模块文件都将是模块接口(而不是模块实现)。如果要将它们与头文件和代码文件进行比较,可以将模块接口视为头文件(.hpp文件),将模块实现视为代码文件(.cpp文件)。

不幸的是,模块提案不允许循环模块接口依赖关系。由于您的程序现在完全由模块接口构成,因此您永远无法拥有任何方式互相依赖的两个模块(这可能会因未来的“声明所有权”声明而得到改进,但目前不支持此功能)。解决循环模块接口依赖的唯一方法是将声明和定义分开,并将循环导入放置在模块实现文件中,而不是循环模块接口依赖关系,允许循环模块实现依赖关系。

以下代码提供了一个无法在不分开声明和定义的情况下编译的示例:

Foo 模块文件

export module Foo;

import module Bar;

export namespace Test {
    class Foo {
    public:
        Bar createBar() {
            return Bar();
        }
    };
}

酒吧模块文件

export module Bar;

import module Foo;

export namespace Test {
    class Bar {
    public:
        Foo createFoo() {
            return Foo();
        }
    };
}

本文提供了一个例子,演示了如果有proclaimed ownership声明的话,如何解决这个问题。实质上,它归结为将声明和定义分开。

在一个完美的世界里,编译器应该能够处理这种情况,但是很遗憾,据我所知,目前提出的模块实现不支持这种情况。


3
我从未认为循环依赖是一件好事,相反,我认为这是一个设计问题。在这个意义上,支持循环依赖真的是一个好主意吗? - BitTickler
4
@BitTickler,我同意您的看法,循环依赖有时确实会暴露出设计问题,但并非总是如此,有时难以避免循环依赖。例如,考虑节点树的情况,每个节点都希望引用其父节点和子节点,这会创建一个循环引用。对于几乎所有的父 <-> 子关系,例如 Player 和 Item 类之间,Player 类引用它拥有的物品,而 Item 类引用其所有者,也是如此。 - Qub1

3
仍然有许多使用头文件的理由。
共享和理解对象api而不看到底层细节的便捷性足以使它们保留下来。它是对象的一个很好的 20 英尺视图,本质上是一个大纲。
如果你正在销售一个库,你会包括一个头文件,以及一个存档文件或共享库。这样你就可以保持信息的专有性,而不会危及你产品的知识产权,你的客户可以包括针对他们目标的二进制编译。
我认为没有头文件是不可能实现的。

2
这里有一个很好的讨论解释了模块化的想法。
简而言之,你是正确的,头文件和实现文件之间的分离将不再需要。 #include指令将被import指令替换,在编译时,模块将提供所需的信息,否则这些信息会在包含的头文件中。

1

这个习语的另一个用途是继承自C;即使对于没有依赖其他翻译单元的翻译单元,它也是一种方便的前向声明手段。

使用预编译头文件直到C++扩展了头文件的使用并因性能原因而必要后,才真正成为重要的事情(尽管有一些非常大的老派头文件,如windows.h)。

这个想法似乎是将更像C#/Java机制引入其中。 C++机制在精神上非常类似Modula / ADA。 让机器为我们做更多的工作会很好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接