C++ 划分C+的工具+;将代码转换为对程序员透明的.h和.cpp文件

C++ 划分C+的工具+;将代码转换为对程序员透明的.h和.cpp文件,c++,ide,C++,Ide,C++是我学过的第一门语言,因此将源代码划分为.h和.cpp文件似乎是显而易见的,但在学习了C#和Java之后,我觉得它们现在非常笨拙。它们在60年代可能很有用,甚至在80年代也可能有用,但在现代工具的时代,比如带有节折叠的IDE和文档生成器,它们似乎已经过时了 无论如何,我的问题是:有没有一种工具可以使这两种文件的存在对程序员透明?例如,让程序员在头文件中写入方法的定义,但实际上将其保存到.cpp文件中 (我知道一个人可以尝试只在头文件中编写一个C++程序,但这不是最好的实践,使程序建立得更长

C++是我学过的第一门语言,因此将源代码划分为.h和.cpp文件似乎是显而易见的,但在学习了C#和Java之后,我觉得它们现在非常笨拙。它们在60年代可能很有用,甚至在80年代也可能有用,但在现代工具的时代,比如带有节折叠的IDE和文档生成器,它们似乎已经过时了

无论如何,我的问题是:有没有一种工具可以使这两种文件的存在对程序员透明?例如,让程序员在头文件中写入方法的定义,但实际上将其保存到.cpp文件中


(我知道一个人可以尝试只在头文件中编写一个C++程序,但这不是最好的实践,使程序建立得更长,实际上两个C++类之间相互引用是不可能的)。这将为您提供一个类的快速概览。当然,这是假设您保持标题简短,并将大多数函数的实现放在.cpp中


此外,您还可以获得VisualStudio插件,该插件将成员函数的实现从标头移动到.cpp中。加上Visual Studio中的“go to definition”和“go to declaration”命令,标题对于导航大型代码库非常有帮助。

我在问题、注释和对其他答案的注释中看到的讨论似乎集中在组件的文本表示上。从纯文本的角度来看,完全删除标题是有意义的

另一方面,头文件和cpp文件的分离还有第二个层次,即将接口与实现分离,并在这样做时从接口中删除实现细节

这以不同的方式发生,在最简单的层面上,您如何实现特定的功能与组件的用户无关[*]。在许多情况下,.cpp文件中可以包含更多类型和函数,这些类型和函数用作实现的详细信息。此外,如果您决定直接或依靠另一个库来实现特定功能,这是实现的一个细节,不应泄露给您的用户

在自动管理文件分离的工具中,这种分离可能很容易实现,也可能不容易实现,而那些喜欢使用仅头库的人则无法实现

当你们中的一些人声称不必去定义,并且希望看到全部代码时,我看到的是决定组件的哪些部分是用户不应该知道的细节的灵活性。在许多IDE中(而且,见鬼,甚至在vim中),都有一个按键组合,可以将您从一个键带到另一个键。在IDE中,您可以重构函数的签名,并让IDE将更改应用于头和实现(有时甚至应用于使用)

如果您想让一个工具提供头和实现的统一视图,那么让工具知道您正在编写的代码的哪些部分是接口或实现的一部分,以及该工具可能做出的决策可能会对生成的程序产生影响,可能会困难得多

独立编译模型有其缺点,但也有其优点,我觉得这里的讨论只是触及了更深层次的设计决策的表面


[*]似乎有相当多的人认为每个类都应该有自己的头文件和.cpp文件,我不同意,每个头文件代表一个组件,可能是单个类,也可能是多个类和自由函数。文件中的代码分离是设计的一部分,在单个组件中,您可能有一个或多个公共类型,同时可能没有或多个内部类型。

我不知道有哪种类型可以使源/头的划分完全透明

然而,我确实知道有一些方法使它更容易处理。例如,VisualAssistX将允许在头中写入整个类,然后选择成员函数,并将它们移动到源文件(即.cpp文件)

这并不是一种完全的治疗方法(无论如何),但它可以/确实让他们更容易忍受


就我个人而言,我认为完全摆脱文件,而直接使用数据库之类的东西会很有趣,也就是说,你有一个函数数据库,其中函数的源代码是一列,目标代码是另一列,内部编译器关于如何使用它的信息,等等。这也会使C++的集成版本控制非常简单(基本上只是一个存储的事务日志)。我认为,如果不将程序员直接暴露于header/cpp拆分,有些事情可能有点难以表达。例如,在某些情况下,以下各项之间存在显著差异:

// header
class Foo {
    Foo() = default;
}

尽管如此,我认为值得考虑改进编译模型或使其更易于处理

例如,我可以想象一个“代码气泡”样式的IDE,程序员在其中编写代码气泡中的定义,然后将气泡组合成翻译单元。程序员将定义标记为“导出”,以使其他TU可以使用这些定义,并为每个TU选择从其他单元导出的项目进行导入。IDE一直在维护它自己的程序代码气泡表示,当您构建它时,它会生成传递给编译器所需的实际cpp文件,创建前向声明
// header
class Foo {
    Foo();
};

// cpp
Foo::Foo() = default;