C ++模板头cpp分离,包含* .cpp到* .h的解决方案不再起作用了

时间:2015-12-02 13:01:05

标签: c++ templates visual-c++

我想将.h和.cpp分开用于模板类。 这就是我在做的事情:

  1. 我直接写了.h和.cpp,没有模板。因此它会创建一个例外Link 2019 Template exception
  2. 有一些解决方案来处理这个How to define template class header and implement it in another cpp。我选择解决方案3。
  3. 根据解决方案,我在#endif内部添加了包含* .cpp的内容。(Still * .cpp包含* .h)(下面的代码代表此步骤)它给出了
      

    模板已经定义错误。

  4. 根据研究,摆脱这个错误的方法是(循环依赖)从* .cpp删除#include * .h但是这次
      

    无法识别的模板声明/定义错误

  5. 发生。我的问题是,如果我将* .cpp包含在* .h文件中。我们如何按预期建造项目?或者这个解决方案是绝对的?

    // TestTemp.h
    #ifndef _TESTTEMP_H_
    #define _TESTTEMP_H_
    template<class T>
    class TestTemp
    {
    public:
        TestTemp();
        void SetValue(T obj_i);
        T Getalue();
    private:
        T m_Obj;
    };
    #include "TestTemp.cpp"
    
    #endif
    
    // TestTemp.cpp
    #include "TestTemp.h"
    template <class T>
    TestTemp<T>::TestTemp()
    {
    }
    template <class T>
    void TestTemp<T>::SetValue(T obj_i)
    {
    }
    
    template <class T>
    T TestTemp<T>::Getalue()
    {
        return m_Obj;
    }
    
    #include "TestTemp.h"
    
    int main()
    {
        TestTemp<int> a;
        a.Getalue();
        return 0;
    }
    

1 个答案:

答案 0 :(得分:3)

与普通类的成员函数不同,模板类的成员函数不能单独编译并链接到可执行文件中。模板的成员必须在编译器可用的位置可见。所有那些荒谬的东西都包含在那篇可怕文章中的内容。

最简单的方法是将定义直接放入模板定义中:

#ifndef TEST_H
#define TEST_H

template <class Ty>
class test {
public:
    void f() { /* whatever */ }
};
#endif

这样做的缺点是较大的类变得不可读(参见Java)。因此,下一步是将定义移到模板外部,但将它们保留在标题中:

#ifndef TEST_H
#define TEST_H

template <class Ty>
class test {
public:
    void f();
};

template <class Ty>
void test<Ty>::f() { /* whatever */ }

#endif

许多人认为这仍然过于混乱,并且希望将定义放入单独的文件中。也没关系,但是每当使用原始标头时,你必须确保包含该单独的文件:

#ifndef TEST_H
#define TEST_H

template <class Ty>
class test {
public:
    void f();
};

#include "test.imp"

#endif

这是文件“test.imp”:

#ifndef TEST_IMP
#define TEST_IMP

template <class Ty>
void test<Ty>::f() { /* whatever */ }

#endif

请注意,“test.imp”实际上是一个头文件,因此它会通过#include "test.imp"中的test.h指令进入您的代码。它不能单独编译,所以应该使用.cpp扩展名来命名,这最多会产生误导。