A. c++primer3中,有一句话:“在多个文件之间编译相同的函数模板定义增加了不必要的编译时间”……
简单点说,对于一个vector<int>的函数,比如size(),如果在不同的cpp中出现,在这些文件编译的时候都要把vector<int>::size()编译一遍。然后在链接的时候把重复的函数去掉。很显然增加了编译时间。
补充里你的理解是错的,模板的声明是不编译的,更没有空间,它根本不是实际的类型或函数,编译器根本不管它。只有实例化的时候,才生成真正的类型、函数,而实例化的地方不在一起,必然造成同一个类型、函数被编译了多次。反观类的编译,只在它的cpp中编译一次,其他地方都使用它的头文件得到声明。
B. 如何制作“以编译HTML文件”,这种形式的东东呀
使用QuickCHM软件轻松编译CHM格式的文件
谈起CHM格式的文件,可能无人不晓,因为几乎所有的软件,现在都用CHM格式的文档制作软件帮助文件。另外,有很大一部分电子图书也是用CHM格式编译的。其实,编译CHM格式的文件很简单,下面就为大家介绍一款制作CHM文件的利器——QuickCHM。
软件名称:QuickCHM
软件大小:1460KB
下载地址:http://www.skycn.com/soft/6785.html
在介绍QuickCHM之前,有必要对CHM的格式作个简单说明。CHM文件格式是微软1998年推出的基于HTML的帮助文件系统,它代替了早先的WinHelp帮助系统,能在Windows 98或NT及以上版本的操作系统中直接运行。
编译CHM
QuickCHM未注册时,只能编辑最多20个节点的项目,在制作CHM文件前,最好把要编译进CHM中的文件编辑成HTML网页文件,CHM格式的文件支持所有的网页元素,所以你可以随心所欲地在Dreamweaver等网页编辑软件中编辑HTML文件。QuickCHM自带一个简易的网页编辑器,利用它可以编辑一些简单的网页,一般的做法是在Dreamweaver中做好网页,然后在QuickCHM中进行局部的修改。
需要注意的是编译进CHM文档中的文件最好都放在同一个文件夹中。
启动QuickCHM,在菜单栏执行“文件→新建”命令,新建一个“hhp”项目。切换到“目录”页,在菜单栏执行“主题→导入→添加文件夹”,导入待编译的文件夹中的文件,注意,在弹出的“添加文件夹”对话框中,可以使用过滤器,防止图片等某些类型的文件进入目录。在默认的情况下,进入目录中的各节点即主题都是以网页标题显示的(如图1),也可以在“系统选项”中设置为以文件名显示。接下来的任务,就是编辑目录和网页,下面就以这两个方面作简单的介绍。
编辑目录:
目录的编辑主要是重命名主题,修改主题图标,排序主题,嵌套主题,新建主题和删除主题,这些都可以利用右键快捷菜单和“目录”页上的按钮完成。
编辑网页:
QuickCHM集成了一个所见即所得的网页编辑器,利用QuickCHM提供的网页编辑工具箱(如图1),可以完成大部分的网页操作。切换到“源文件”页,可以对HTML源代码进行直接修改。和多数网页编辑软件一样,切换到“预览”页,可以对当前网页实时预览。
图1
利用同样的方法,还可以给帮助系统做一个“索引”页。
目录和网页编辑完成以后,就可以输出CHM文档了,不过在输出前也可以把它保存为一个“.hhp”项目,以便日后继续编辑。点击工具栏上的“编译”按钮,编译完成,如图2所示,这是利用上述的方法制作的“瑞星杀毒软件2004版”的帮助系统,从图中可以看出,这个帮助系统的“面板”上只有“目录”页,没有“索引”页。
图2
事实上,CHM文件的这个阅读平台即“浏览窗体”的所有部分都可以在“编译”前进行修改和定制,若你做进CHM帮助系统的各网页间都能相互导航,我们甚至可以隐藏或关闭整个“面板”。
在菜单栏上执行“选项→项目选项”命令,弹出“参数”对话框,如图3所示,在这里可以设定“主页”、“默认页”,显示或隐藏工具栏按钮和标题,显示或隐藏面板及面板上的目录、索引等,在这里还可以设定目录的表现方式和整个窗体的外观,添加“闪屏”(启动时一个一闪而过的图片,相当于软件的启动画面)等,当然了,以上的所有设置必须在“编译”前设置才能看到效果。
图3
反编译CHM
QuickCHM不仅能把HTML网页、文本文件、图片等编译为一个CHM文件, 而且还能反编译一个CHM文件,也就是说,利用QuickCHM,可以释放CHM文件中的HTML文件、文本文件、图片文件等资源,并且它能够恢复源文件的全部目录结构和文件名,以便帮助我们得到源文件进行资料恢复或二次编辑。
启动QuickCHM,在菜单栏执行“文件→反编译”,在弹出的对话框中选择要进行反编译的CHM文件以及反编译得到的HTML文件和图片等其它文件资源的保存位置,点击“确定”,反编译即可完成,同时保存HTML文件和图片等其它文件的文件夹被打开。
C. 如何编译SublimeText3主题文件
新建一个文件,保存为html格式,输入html按一下tab键就可以了 这是系统内置的模板,还可以自定义,输入一个关键词,按一下tab键,就能自动完成。很方便
D. ctex编译论文模板出错,报错如下:
我发现将.tex的文件,也就是你要编译的文件放入 \ctex\MiKTeX\miktex\bin\ 是可以编译的,我今天也这折腾了好久,因为一直都编译不了,我还找过在线编译,但是在线的特别烂,还一直都说我的模板是错的,。。。无语,结果编译后可以出pdf,放心吧,这方法我才实践过~~注意这个比如是在你安装了完整的CTeX前提下哦!其他好像还有别的方法我只是试过没什么用
E. 别人写的latex模板为啥无法编译啊
那要看具体情况. 有如下的几种情况:
(1) 代码有误;
(2) 你计算机里面的 Mitex 或 texlive 没有所需的宏包;
(3) 编译的方法不对;
(4) 编译的源文件的文件类型不同,如utf8 和 GBK
总之,你这样问问题还是很难解决的,要把具体错误的信息和代码贴出来,才可能解决.
F. 为什么C++编译器不能支持对模板的分离式编译
当编译器将一个工程里的所有.cpp文件以分离的方式编译完毕后,再由连接器(linker)进行连接成为一个.exe文件。 举个例子: //---------------test.h-------------------//void f();//这里声明一个函数f //---------------test.cpp--------------//#include”test.h”void f(){…//do something} //这里实现出test.h中声明的f函数 //---------------main.cpp--------------//#include”test.h”int main(){f(); //调用f,f具有外部连接类型} 在这个例子中,test. cpp和main.cpp各自被编译成不同的.obj文件(姑且命名为test.obj和main.obj),在main.cpp中,调用了f函数,然而当编译器编译main.cpp时,它所仅仅知道的只是main.cpp中所包含的test.h文件中的一个关于void f();的声明,所以,编译器将这里的f看作外部连接类型,即认为它的函数实现代码在另一个.obj文件中,本例也就是test.obj,也就是说,main.obj中实际没有关于f函数的哪怕一行二进制代码,而这些代码实际存在于test.cpp所编译成的test.obj中。在main.obj中对f的调用只会生成一行call指令,像这样: call f [C++中这个名字当然是经过mangling[处理]过的] 在编译时,这个call指令显然是错误的,因为main.obj中并无一行f的实现代码。那怎么办呢?这就是连接器的任务,连接器负责在其它的.obj中(本例为test.obj)寻找f的实现代码,找到以后将call f这个指令的调用地址换成实际的f的函数进入点地址。需要注意的是:连接器实际上将工程里的.obj“连接”成了一个.exe文件,而它最关键的任务就是上面说的,寻找一个外部连接符号在另一个.obj中的地址,然后替换原来的“虚假”地址。 这个过程如果说的更深入就是: call f这行指令其实并不是这样的,它实际上是所谓的stub,也就是一个jmp 0xABCDEF。这个地址可能是任意的,然而关键是这个地址上有一行指令来进行真正的call f动作。也就是说,这个.obj文件里面所有对f的调用都jmp向同一个地址,在后者那儿才真正”call”f。这样做的好处就是连接器修改地址时只要对后者的call XXX地址作改动就行了。但是,连接器是如何找到f的实际地址的呢(在本例中这处于test.obj中),因为.obj与.exe的格式是一样的,在这样的文件中有一个符号导入表和符号导出表(import table和export table)其中将所有符号和它们的地址关联起来。这样连接器只要在test.obj的符号导出表中寻找符号f(当然C++对f作了mangling)的地址就行了,然后作一些偏移量处理后(因为是将两个.obj文件合并,当然地址会有一定的偏移,这个连接器清楚)写入main.obj中的符号导入表中f所占有的那一项即可。 这就是大概的过程。其中关键就是: 编译main.cpp时,编译器不知道f的实现,所以当碰到对它的调用时只是给出一个指示,指示连接器应该为它寻找f的实现体。这也就是说main.obj中没有关于f的任何一行二进制代码。 编译test.cpp时,编译器找到了f的实现。于是乎f的实现(二进制代码)出现在test.obj里。 连接时,连接器在test.obj中找到f的实现代码(二进制)的地址(通过符号导出表)。然后将main.obj中悬而未决的call XXX地址改成f实际的地址。完成。 然而,对于模板,你知道,模板函数的代码其实并不能直接编译成二进制代码,其中要有一个“实例化”的过程。举个例子: //----------main.cpp------//template<class T>void f(T t){} int main(){…//do somethingf(10); // call f<int> 编译器在这里决定给f一个f<int>的实例…//do other thing} 也就是说,如果你在main.cpp文件中没有调用过f,f也就得不到实例化,从而main.obj中也就没有关于f的任意一行二进制代码!如果你这样调用了: f(10); // f<int>得以实例化出来f(10.0); // f<double>得以实例化出来 这样main.obj中也就有了f<int>,f<double>两个函数的二进制代码段。以此类推。 然而实例化要求编译器知道模板的定义,不是吗? 看下面的例子(将模板的声明和实现分离): //-------------test.h----------------//template<class T>class A{public:void f(); // 这里只是个声明}; //---------------test.cpp-------------//#include”test.h”template<class T>void A<T>::f() // 模板的实现{ …//do something} //---------------main.cpp---------------//#include”test.h”int main(){A<int> a;f(); // #1} 编译器在#1处并不知道A<int>::f的定义,因为它不在test.h里面,于是编译器只好寄希望于连接器,希望它能够在其他.obj里面找到A<int>::f的实例,在本例中就是test.obj,然而,后者中真有A<int>::f的二进制代码吗?NO!!!因为C++标准明确表示,当一个模板不被用到的时侯它就不该被实例化出来,test.cpp中用到了A<int>::f了吗?没有!!
G. STM32为什么我按照模板添加了文件还是编译不成功
你可以在头文件中定义 数据类型 struct student{} 和 函数
然后主函数中调用加上#include <myproject.h> 在这个头文件里的实现函数 要是正确的能够通过编译的
其实也可建议你写一个dll
或则你直接把数据类型 struct student{} 变量为全局变量 各个函数都可以调用 挺好的
H. C++中模板的编译与文件部署问题
模板这玩意不在当前编译单元(也就是cpp)里使用就不会被编译(想编译也编译不了,起码不完整) 所以一般要么写在和调用同一个cpp里,要么完全写在.h里(不是把声明写.h里把定义写在.cpp里,直接把定义写在.h里)
模板不会产生定义重复问题。 (指链接的时候... 你怎么搞出重复定义的我还真想不出来...)
第三个问题没看明白bbb
--
#include的功能...就是把一个文件的内容直接粘贴到当前文件...
比如是
a.cpp
1
#include "b.h"
2
b.h
3
与处理后就会有a.i
1
#line 1 "b.h"
3
#line 3 "a.cpp"
2
这种结果,只是把b.h的内容插入了#include "b.h"的位置。那两个#line不用管,是为了正确返回错误出现位置用的。
--
模板必须有定义因为必须在使用的时候补完。你不使用根本没办法编译模板。
比如你在a.cpp里写了一个模板,b.cpp里使用这个模板。a.cpp里并没有使用模板所以根本没有编译(模板只有使用的时候才能提供编译需要的参数)。b.cpp里使用的话,根本链接不到相应的代码。
I. 用Latex编译国外期刊模板时, 显示enter the file, entering extended mode
应该是缺少宏包, 具体看日志.
编辑引擎现在一般都使用的是 LaTeX 格式, TeX 格式的文档很少使用了.
除了 pdfLaTeX , 再试一试 XeLaTeX.
J. 请问一下c++多文件模板编译 a.cpp 和a.h 生成liba.so 在usea 中调用 a.cpp 里面有定义模板 谢谢
目前基本没有 C++ 编译器支持template分离编译吧
模板函数实现放到头文件里