zoukankan      html  css  js  c++  java
  • C++中模板不能把实现和声明放在两个不同的文件下

    http://zhidao.baidu.com/question/322405048.html

    http://www.zhihu.com/question/20630104

    http://bbs.chinaunix.net/thread-923716-1-1.html

    在Fraction.h中,我是这么定义的
    #pragma once
    #ifndef FRACTION
    #define FRACTION
    template<class T>
    class Fraction
    {
    public:
    Fraction(void);
    Fraction(T ,T);
    ~Fraction(void);
    private:
    T numerator;//分子
    T denominator;//分母
    };
    #endif
    在Fraction.cpp中我是这么实现的
    #include "StdAfx.h"
    #include "Fraction.h"

    template<class T>
    Fraction<T>::Fraction(void):numerator(0),denominator(0)
    {
    }

    template<class T>
    Fraction<T>::Fraction(T numerator,T denominator)
    {
    this->numerator=numerator;//分子
    this->denominator=denominator;//分母
    }

    template<class T>
    Fraction<T>::~Fraction(void)
    {
    }

    主函数调用如下
    #include "stdafx.h"
    #include"Fraction.h"

    int _tmain(int argc, _TCHAR* argv[])
    {
    Fraction<int> ftion(10,120);
    return 0;
    }

    提示如下错误
    1>One.obj : error LNK2019: unresolved external symbol "public: __thiscall Fraction<int>::~Fraction<int>(void)" (??1?$Fraction@H@@QAE@XZ) referenced in function _wmain
    1>One.obj : error LNK2019: unresolved external symbol "public: __thiscall Fraction<int>::Fraction<int>(int,int)" (??0?$Fraction@H@@QAE@HH@Z) referenced in function _wmain
    1>F:\DataStruct\ChapterOne\One\Debug\One.exe : fatal error LNK1120: 2 unresolved externals
    1>Build log was saved at "file://f:\DataStruct\ChapterOne\One\One\Debug\BuildLog.htm"
    1>One - 3 error(s), 0 warning(s)

     两个解决方案:
    ①将Fraction.h和Fraction.cpp文件写到一个文件中,即Fraction.h头文件。
    ②将Fraction.cpp改名为Fraction.template文件,然后再Fraction.h倒数第一行#endif之前加入一行代码 #include "Fraction.template"即可。 

    这个是初学者常见问题了。

    简而言之,目前绝大多数C++编译器不支持将模版类/模版函数的声明与实现分开。
    所以你要写就全部一起写在头文件中,不要分开写到两个文件中。或者像楼上所说在头文件中再#include一次(不过没啥意义)。

    这个是C++的一个老顽固问题了,虽然C++标准有规定通过export关键字来实现模版的分离编译,但是因为实现过于复杂,实际上几乎没有编译器鸟它。VC、BC、GCC都不支持。(貌似只有ICC部分支持)

    所以你也只能向现实妥协了呵呵,就像STL一样,把模版函数和模版类的实现全部写在.h头文件中吧。

    @欲三更 邀,这个问题让我想起我在实习的时候犯的一个错误,就是把模版类的定义和实现分开写了,结果编译出错,查了两天才查出问题。

    C++ 中每一个对象所占用的空间大小,是在编译的时候就确定的,在模板类没有真正的被使用之前,编译器是无法知道,模板类中使用模板类型的对象的所占用的空间的 大小的。只有模板被真正使用的时候,编译器才知道,模板套用的是什么类型,应该分配多少空间。这也就是模板类为什么只是称之为模板,而不是泛型的缘故。

    既 然是在编译的时候,根据套用的不同类型进行编译,那么,套用不同类型的模板类实际上就是两个不同的类型,也就是说,stack<int>和 stack<char>是两个不同的数据类型,他们共同的成员函数也不是同一个函数,只不过具有相似的功能罢了。如 上图所示,很简短的六行代码,用的是STL里面的stack,stack<int>和stack<char>的默认构造函数和 push函数的入口地址是不一样的,而不同的stack<int>对象相同的函数入口地址是一样的,这个也反映了模板类在套用不同类型以后, 会被编译出不同代码的现象。

    所以模板类的实现,脱离具体的使用,是无法单独的编译的;把声明和实现分开的做法也是不可取的,必须把实现全部写在头文件里面。为了清晰,实现可以不写在class后面的花括号里面,可以写在class的外面。

    另外提供一些参考:
    stackoverflow.com/question

    目前大部分的C++编译器要求把模版的定义和实现都放在头文件中,而不能支持分开编译的方式。
    C++标准中有一个export关键来解决这个问题,但现在大部份的编译器并不能支持它。

  • 相关阅读:
    北京 到 娄底 灌湄
    AVR--IO设置编程
    AVR--I/O端口寄存器
    AVR--IO结构分析
    虚拟机VM下 UBUNTU 下安装Mantis
    Windows环境下Mantis搭建概述
    SW4STM32 : Error message from debugger back end: Error erasing flash with vFlashErase packet Error erasing flash with vFlashErase packet
    三极管驱动继电器详解
    STM32 Bootloader 跳转到App
    (转载) STM32IAP升级---IAP升级功能编写初期的一些困惑与疑问---完成功能后的总结
  • 原文地址:https://www.cnblogs.com/androidme/p/2900241.html
Copyright © 2011-2022 走看看