C++ 模板头 cpp 分离,将 *.cpp 包含到 *.h 中的解决方案不再有效

标签 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. 根据解决方案,我在 header 内的#endif 之前添加了 include *.cpp。(仍然 *.cpp 包括 *.h)(下面的代码表示此步骤) 它给出了

    template has already been defined error.

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

    unrecognizable template declaration/definition error

发生了。我的问题是我是否将 *.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;
}

最佳答案

与普通类的成员函数不同,模板类的成员函数不能单独编译链接成可执行文件。模板的成员在使用时必须对编译器可见。这就是那篇可怕的文章中所有荒谬的内容。

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

#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

很多人觉得那还是太杂乱了,想把定义放在一个单独的文件里。这也没关系,但是您必须确保在使用原始 header 时包含该单独的文件:

#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”实际上是一个头文件,因此它通过 test.h 中的 #include "test.imp" 指令进入您的代码.它不能单独编译,因此 应该用 .cpp 扩展名命名,这充其量只会产生误导。

关于C++ 模板头 cpp 分离,将 *.cpp 包含到 *.h 中的解决方案不再有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34043432/

相关文章:

c++ - 对话框背景和单选按钮透明度

c++ - 使用 std::make_unique 构造实例时类模板推断类型的方式?

visual-c++ - 如何加载tiff文件并将其保存为vc++中的bmp

c++ - std::_Atomic_thread_fence(大写字母 A)是否正确?

c++ - 如何编写采用通用 C++ 标准库容器的模板函数

c++ - VC++的开端

c++ - SFML sprite.move() 不工作

c++ - __vfptr 表在未删除的对象中损坏

c++ - 如何通过 C++ 中的一个 cout 语句计算中间零和前导零?

c++ - 参数包扩展遇到问题