精华内容
下载资源
问答
  • 模板的分离编译

    2017-11-19 15:45:20
    模板 分离编译 图片

    非模板函数:


    模板函数:

    展开全文
  • 主要介绍了详解C++函数模板与分离编译模式的相关资料,帮助大家更好的理解和学习c++,感兴趣的朋友可以了解下
  • C++模板与分离编译

    2018-02-24 22:54:33
    分离编译模式 一个项目如果有多个源文件组成,每个源文件单独编译,形成目标文件。最后通过链接器将所有的目标文件链接起来,形成一个可执行的文件。这个过程就叫做分离编译。 模板不能分离编译 有一个项目,...

    个人博客传送门

    分离编译模式

    一个项目如果有多个源文件组成,每个源文件单独编译,形成目标文件。最后通过链接器将所有的目标文件链接起来,形成一个可执行的文件。这个过程就叫做分离编译。

    模板不能分离编译

    有一个项目,其中函数声明放在”test.h”中,函数实现放在”test.cpp”中,函数调用放在”main.cpp”中。如果没用使用模板,将不会有任何问题。而且这样是被推荐使用的。但是如果有函数的实现是模板函数或有模板类,将会出现链接错误。代码如下:

    //test.h
    #pragma once
    
    template <class T>
    void print(T num);
    
    //test.cpp
    template <class T>
    void print(T num){ cout << num << endl; }
    
    //main.cpp
    #include <iostream>
    #include "test.h"
    using namespace std;
    
    int main(){
        int number = 10;
        print(number);
        return 0;
    }

    这样的代码看起来是没有问题的。执行的时候并不会出现编译错误,但是会出现链接错误。
    链接错误
    这是因为采取了分离编译之后,我们的.cpp文件是独立编译的。test.cpp中的模板函数,由于没有被调用,所以它的T并没有被实例化相应的类型,比如例子中的int类型。main.cpp中调用了函数print,他需要实例print(int num)。在链接的时候,找不到需要的实例化函数,这样就产生了错误。

    解决办法1-显示实例化

    在函数定义的时候,指定我们需要实例化的类型。在头文件定义中添加指定类型的定义:

    #pragma once
    
    template <class T>
    void print(T num);
    //添加int定义
    template void print<int>(int num);

    这种方式是最简单,但是这样却是最麻烦的。如果我有多个不同类型,就需要有相应个数的特化。

    解决办法2-不使用分离编译

    既然不能使用,那么我们不使用分离编译就是了。将我们的函数声明和函数定义放在test.h中。这样我们编译的时候,需要将头文件展开,这样就可以将模板函数在编译的时候实例化。

    //test.h
    //不需要test.cpp
    #pragma once
    
    template <class T>
    void print(T num){ cout << num << endl; }

    这样解决了模板的分离编译的问题,但是这样也就暴露了我们的函数定义。

    展开全文
  • 分离编译模式简介

    千次阅读 2015-10-03 16:54:58
    分离编译模式源于C语言,在C++语言中继续沿用。简单地说,分离编译模式是指:一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件连接起来形成单一的可执行文件的过程。

    示例代码编译运行环境:Windows 64bits+VS2017+Debug+Win32。


    1.分离编译模式的定义

    分离编译模式源于C语言,在C++语言中继续沿用。简单地说,分离编译模式是指一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件(obj文件),最后将所有目标文件连接起来形成单一的可执行文件的过程。

    2.分离编译模式的由来

    分离编译模式是C/C++组织源代码和生成可执行文件的方式。在实际开发大型项目的时候,不可能把所有的代码都写在一个文件中,而是分别由不同的程序员开发不同的模块,再将这些模块汇总成为最终的可执行程序。

    这里就涉及到不同的模块(源文件)定义的函数和变量之间的相互调用问题。C/C++语言所采用的方法是:只要给出函数原型(或外部变量声明),就可以在本源文件中使用该函数(或变量)。每个源文件都是独立的编译单元,在当前源文件中使用但未在此定义的变量或者函数,就假设在其他的源文件中定义好了。每个源文件生成独立的目标文件,然后通过连接(Linking)将目标文件组成最终的可执行文件。

    程序编译过程包括预处理(Preprocessing)、编译(Compilation)、汇编(Assembly)和连接(Linking)。

    3.分离编译模式的的要点

    理解分离编译模式要注意以下几点。

    (1)每个函数或外部变量(全局变量)只能被定义一次,但可以被多次“声明”。
    考察如下程序。

    #include <iostream>
    using namespace std;
    void func();
    void func();
    void func()
    {
        cout<<”This ia a demo”<<endl;
    }
    
    int main()
    {
        func();
    }

    函数func()被多次声明,并不影响程序的正常编译和运行。在一个源文件中允许同时包含定义和声明同一个标识符的语句,这样可以通过前置申明做到先使用后定义。

    (2)函数声明也是有作用域的。
    类的成员函数只能在类体中声明。对于外部函数,如果是在一个函数体内声明另一个外部函数,那么该函数声明的作用域就是从声明处开始到函数体结束为止。在别的位置要调用这个函数,需要再次声明。

    如下面的程序,由两个源文件组成,a.cpp和b.cpp。函数func()定义在a.cpp中,b.cpp中有两个函数show()和main()都调用了a.cpp中定义的函数func()。如果坚持将函数声明放在函数体内部,则在函数show()和main()中必须分别对函数func()进行声明,否则编译出错。程序如下:

    /***a.cpp***/
    #include <iostream>
    Using namespace std;
    void func()
    {
        cout<<”This is a demo”<<endl;
    }
    /***end of a.cpp***/
    
    /***b.cpp***/
    void show()
    {
        void func(); //func()的声明必不可少
        func();
    }
    
    int mian()
    {
        void func(); // func()的声明必不可少
        func();
        show();
    }
    /***end of b.cpp***/

    通常情况下,将外部函数或外部变量的声明放在.h头文件中。对于不在源文件中定义的函数(或变量),只要将相应的头文件通过#include指令包含进来,就可以正常使用了。

    (3)一个函数被声明却从未定义,只要没有发生函数调用,编译连接是不会出错的。
    参考如下程序。

    #include <iostream>
    using namespace std;
    class Demo
    {
    public:
        void func1();
        void func2();
    };
    void Demo::func1()
    {
        cout<<”This is a demo”<<endl;
    }
    
    int main()
    {
        Demo obj;
        obj.func1();
    }   

    观察以上程序可以,类Demo的定义是不完整的,因为成员函数func2未完成定义,但是func2从未发生过调用,所以,函数只有申明没有定义在不发生函数调用的情况下是可以通过编译连接的。

    从分离编译模式的角度来看,函数Demo::func2()有可能定义在别的源文件中,参考如下程序。

    /***a.cpp***/   
    #include <iostream>
    using namespace std;
    class Demo
    {
    public:
        void func1();
        void func2();
    };
    void Demo::func2()
    {
        cout<<”This is func2”<<endl;
    }   
    /***end of a.cpp***/    
    
    /***a.cpp***/
    #include <iostream>
    using namespace std;
    class Demo
    {
    public:
        void func1();
        void func2();
    };
    void Demo::func1()
    {
        cout<<”This is func1”<<endl;
    }
    
    int main()
    {
        Demo obj;
        obj.func2();
    }
    /***end of b.cpp***/    

    观察以上程序,类Demo有两个成员函数,它们分别在a.cpp和b.cpp源文件中实现。类Demo是被“分离“实现的。所以,分离编译模式关心的是函数的调用规范(函数原型),至于函数是否真正实现要到连接的时候才能被发现。

    由分离编译模式也可以得出头文件的书写规范。头文件的目的是提供其他源文件中定义的,可以被当前源文件使用的内容(函数、变量等)的声明,所以头文件可能要多次被不同的源文件包含,因此一般都不在头文件中定义函数或外部变量,因为这样的头文件只能被包含一次。

    在一个源文件中定义函数,在另一个源文件中调用该函数,是分离编译模式下十分普遍的现象,但是如果定义的不是一个普通函数,而是一个函数模板,可能会发生错误。关于模板的使用规范,参见模板与分离编译模式


    参考文献

    [1]陈刚.C++高级进阶教程[M].武汉:武汉大学出版社,2008

    展开全文
  • 类模板的分离编译 类模板的分离编译,即模板类的定义和其模板成员函数(接口)的定义不在同一文件中。如模板类的定义在.h头文件中,同时在.h头文件中声明接口,而在模板类之外的.cpp文件中定义接口。此时在main函数...

    类模板的分离编译

    类模板的分离编译,即模板类的定义和其模板成员函数(接口)的定义不在同一文件中。如模板类的定义在.h头文件中,同时在.h头文件中声明接口,而在模板类之外的.cpp文件中定义接口。此时在main函数中,如果只引用.h头文件,编译会报错。

    原因:大多数编译器,不支持类模板的分离编译!

    (1)实现分离编译
    其实也可以实现分离编译。解决办法:在main函数中引用定义接口的.cpp文件,这时编译就可以通过了。

    // SeqList.h
    template <class DataType>
    class SeqList
    { ... };
    
    
    
    // SeqList.cpp中
    #include "SeqList.h"
    
    template <class DataType>
    SeqList<DataType>::函数()  { ... }
    
    
    
    // main.cpp中
    #include "SeqList.cpp"
    
    int main() { 
    
    	... 
        return 0;
    }
    

    (2)类模板的接口与实现放在一起
    建议把类模板的接口与实现放在一起

    // SeqList.h
    template <class DataType>
    class SeqList
    { ... };
    
    template <class DataType>
    SeqList<DataType>::函数()  { ... }
    
    
    
    // main.cpp中
    #include "SeqList."
    
    int main() { 
    
    	... 
        return 0;
    }
    

    推荐:关于类模板分离编译的问题解析,看这里:
    细谈 C++ 类模板的分离式编译:类模板究竟要不要接口与实现分离

    展开全文
  • 模板的分离编译1.模板的分离编译=模板+分离编译2.对于模板我们并不陌生,但什么是分离编译呢?,分离编译即就是:一个程序有若干个源文件(.cpp文件)共同实现,而每个源文件单独生成目标文件(.obj文件),最后将...
  • 1.分离编译模式: 一个程序由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有的目标文件链接起来形成但一个可执行文件的过程称为分离编译模式。 但是这种分离编译在C++中是不支持的。 2....
  • C++ -- 模板与分离编译

    2018-06-01 18:14:39
    什么是分离编译 1.将一个函数或类的声明放在.h文件里面,将其代码实现放在同名的.cpp里面,当调用该函数时,该函数就会进行分离编译。 2.以add函数为例:(定义一个函数Add,将其函数声明放在Add.h里面,将其实现...
  • 模板函数的分离编译

    2017-09-10 20:10:22
    在介绍分离编译之前,应当先做到对基本的程序编译过程有一定的了解。 下面图文并茂的理解一下这个过程。在这个编译器工作过程中,最主要的是明白:最终的所有的目标文件.o链接起来生成单一的可执行程序的过程. ...
  • 类模版的分离编译

    2016-05-15 22:32:23
    普通函数不需要分离编译而模版函数需要分离编译 1、对于普通函数:vodi Fun() 在Fun.h文件中声明如下: void Fun();在Fun.cpp中定义如下: #include"Fun.h" void Fun() { cout ()" ; }测试用例如下: #include"Fun...
  • 首先我们需要了解什么是分离编译分离编译: 一个程序(项目)有诺干个源文件共同实现,而每个文件单独编译生成目标文件,最后将所有目标文件链接取来形成单一的可执行文件的过程为分离编译 我们可以看下面的...
  • 下面用一副图来说明末班的分离编译这里就是普通的代码,是可以进行分离编译的,但是为什么在模板中就不可以了呢,下面我们来看一段简单的代码,来进行分析//template.h template class AA { public: AA(); private:...
  • C++ 函数模板与分离编译模式

    千次阅读 2015-10-30 00:56:14
    一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件连接起来形成单一的可执行文件的过程成为分离编译模式。2.使用模板在连接时出错在C++程序设计中,在一个源文件中...
  • 首先我要介绍分离编译的概念?一个程序由若干个原文件共同实现,每个源文件单独编译生成目标文件,然后再将所有的目标文件链接起来生成单一的可执行程序的过程.ps.我所理解的分离编译就是不在同一个.h或.cpp文件中定义...
  • 模板为什么不支持分离编译 通常我们习惯于将函数分离编译,即: 对于一个函数fun 分离编译: 在xx.h中给出函数定义 在xx.cpp中完成函数 在xxmain.cpp中调用函数 先看一般情况下,编译器如何对函数分离...
  • 但是,像下面这样将模板函数分离编译时,在测试函数编译时就会报错。//template.h#pragma once template<class T>class MyClass { public: void Func();//只声明,定义在其他文件 }; //templat.cpp 函数的定义 #...
  • C++中的模板不支持分离编译 按照我们之前的习惯,写出的代码是这样的 // Template.h #pragma once #include &amp;lt;stdio.h&amp;gt; #include &amp;lt;iostream&amp;gt; using namespace std; ...
  • 如下图所示,在模板函数运行要经历预处理,编译,汇编,链接几个过程,前三个都没有问题,但是在链接时,因为是模板函数,没有实例化出代码,尽管生命了,却没有定义,所以不支持分离编译。解决办法一是显示实例化...
  • 模板类究竟为什么不支持分离编译呢?!! 究竟是为什么呢!!!
  • C++高阶 论分离编译

    千次阅读 2021-04-29 09:57:23
    五一待写。
  • 模板类(函数)的分离编译(Separate compile)问题  模板是一把双刃剑,Template的出现极大的简化了代码的重复,同时也增加了阅读代码的难度。很多复杂的Template 类是令人望而生畏的,再加上宏定义,可以直接进入...
  • 1)使用模板的cpp文件实现不能分离编译,也就是模板的声明和实现都要在同一个.h文件中,然后.cpp 文件调用就好了。如果非要分离编译,就会导致链接错误了。 2)main.cpp不允许直接去调用另一个.cpp文件,这样也会...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 190,432
精华内容 76,172
关键字:

分离编译