c – 如何避免包含类实现文件?
而不是做
#include "MyClass.cpp" 我想要做 #include "MyClass.h" 我在网上看到,不这样做被认为是不好的做法. 解决方法
简而言之,单独编译
首先,我们来看一些简单的例子: struct ClassDeclaration; // 'class' / 'struct' mean almost the same thing here struct ClassDefinition {}; // the only difference is default accessibility // of bases and members void function_declaration(); void function_definition() {} extern int global_object_declaration; int global_object_definition; template<class T> // cannot replace this 'class' with 'struct' struct ClassTemplateDeclaration; template<class T> struct ClassTemplateDefinition {}; template<class T> void function_template_declaration(); template<class T> void function_template_definition() {} 翻译单位 翻译单元(TU)是单个源文件(应该是** .cpp *文件)及其包含的所有文件,它们包括等等.换句话说:预处理单个文件的结果. 头 包含防护是一种破解工作,缺乏真正的模块系统,使标头成为一种有限的模块;为此,包括同一标题不止一次不得产生不利影响. 通过制作后续的#includes no-ops来包括警卫工作,其中的定义可从第一个包含.由于它们的性质有限,控制标题选项的宏在整个项目中应该是一致的(奇怪的标题,如< assert.h>导致问题),所有#includes的公共标题应该在任何名称空间,类等之外,通常在任何文件的顶部. 查看我的包含守卫naming advice,包括到generate include guards的短程序. 声明 类,函数,对象和模板几乎可以在任何地方声明,可以声明任意次数,并且必须在以任何方式引用它们之前声明.在一些奇怪的情况下,您可以在使用它们时声明类;这里不会涵盖. 定义 每个TU最多可以定义一次[1];当您为特定类包含标头时,通常会发生这种情况.函数和对象必须在一个TU中定义一次;当您在** .cpp *文件中实现它们时,通常会发生这种情况.但是,内联函数(包括类定义中的隐式内联函数)可以在多个TU中定义,但定义必须相同. 出于实际目的[2],模板(类模板和函数模板)仅在头文件中定义,如果要使用单独的文件,则使用另一个头文件[3]. [1]由于最多一次的限制,标题使用包含防护来防止多重包含,从而防止多个定义错误. 方针 所以,虽然我确定上面的所有内容到目前为止都是一个很大的漏洞,但它不应该是一篇关于应该占用几章的页面,所以将它作为一个简短的参考.但是,理解上述概念很重要.使用这些,这里是一个简短的指南列表(但不是绝对规则): >始终在单个项目中始终为标题命名,例如**.h *表示C,**.hpp *表示C. 构建过程 (这是回答你的问题的一小部分,但你需要上面的大部分才能到达这里.) 在构建时,构建系统将经历几个步骤,其中重要的步骤是: >将每个实现文件编译为TU,生成目标文件(**.o *,**.obj *) >每个都是独立编译的,这就是每个TU需要声明和定义的原因 >将这些文件以及指定的库链接到单个可执行文件中 我建议你学习制作的基本知识,因为它很受欢迎,很容易理解,而且很容易上手.但是,它是一个有几个问题的旧系统,你需要在某个时候切换到别的东西. 选择一个构建系统几乎是一种宗教体验,比如选择一个编辑器,除了你必须与更多人(每个人在同一个项目上工作)合作,并且可能会受到先例和惯例的限制.你可以使用一个为你处理相同细节的IDE,但是使用全面的构建系统并没有真正的好处,你真的应该知道它在做什么. 文件模板 example.hpp #ifndef EXAMPLE_INCLUDE_GUARD_60497EBE580B4F5292059C8705848F75 #define EXAMPLE_INCLUDE_GUARD_60497EBE580B4F5292059C8705848F75 // all project-specific macros for this project are prefixed "EXAMPLE_" #include <ostream> // required headers/"modules"/libraries from the #include <string> // stdlib,this project,and elsewhere #include <vector> namespace example { // main namespace for this project template<class T> struct TemplateExample { // for practical purposes,just put entire void f() {} // definition of class and all methods in header T data; }; struct FooBar { FooBar(); // declared int size() const { return v.size(); } // defined (& implicitly inline) private: std::vector<TemplateExample<int> > v; }; int main(std::vector<std::string> args); // declared } // example:: #endif example.cpp #include "example.hpp" // include the headers "specific to" this implementation // file first,helps make sure the header includes anything it needs (is // independent) #include <algorithm> // anything additional not included by the header #include <iostream> namespace example { FooBar::FooBar() : v(42) {} // define ctor int main(std::vector<std::string> args) { // define function using namespace std; // use inside function scope,if desired,is always okay // but using outside function scope can be problematic cout << "doing real work now...n"; // no std:: needed here return 42; } } // example:: main.cpp中 #include <iostream> #include "example.hpp" int main(int argc,char const** argv) try { // do any global initialization before real main return example::main(std::vector<std::string>(argv,argv + argc)); } catch (std::exception& e) { std::cerr << "[uncaught exception: " << e.what() << "]n"; return 1; // or EXIT_FAILURE,etc. } catch (...) { std::cerr << "[unknown uncaught exception]n"; return 1; // or EXIT_FAILURE,etc. } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |