c++ 多文件模板实现

6bc51xsx  于 2023-05-02  发布在  其他
关注(0)|答案(4)|浏览(251)

对于普通函数,声明和定义通常在多个文件中分开,如下所示:

// Foo.h

namespace Foo
{
    void Bar();
}

.

// Foo.cpp

#include "Foo.h"

void Foo::Bar()
{
    cout << "Inside function." << endl;
}

这是我的理解,这不能做的模板。声明和定义不能分开,因为模板的适当形式是在需要时“按需”创建的。
那么,在像这样的多文件项目中,模板通常是如何定义的,定义在哪里?我的直觉是,它应该在Foo.cpp中,因为这是函数的“肉”通常在哪里,但另一方面,它是将要包含的头文件。

amrnrhlw

amrnrhlw1#

类中编写模板化方法的定义。hxx文件并将其包含在头文件的末尾(.hh)在其中声明。.cc/.cpp用于定义非模板化方法。
所以你会有一个。hh、一个.hxx(包含在.hh)和一个。cc;这样包含模板化的类头文件也会包含它的定义。
示例:

// list.hh
#IFNDEF LIST_HH
# DEFINE LIST_HH

template <typename T>
class List
{
  void fun1(T a);

  void fun2();
}

# include "list.hxx"

#ENDIF

// list.hxx
#IFNDEF LIST_HXX
# DEFINE LIST_HXX

# include "list.hh"

template <typename T>
void List::fun1(T a)
{
   // ...
}

#ENDIF

// list.cc

#include "list.hh"

void List::fun2()
{
   // ...
}

// anywhere.cc

#include "list.hh"

// ...

编辑

有几种编译模板的策略。最常见的策略是上面描述的让类模板的每个用户示例化代码的策略。
因为 *。hh文件包含 *。hxx文件,每次需要一个模板的简单声明时,完整的实现都会随之而来。如果实现需要其他声明,如std::string,则强制所有客户端代码解析字符串头。
为了避免多次示例化(消耗时间和空间),可以引入第四种类型的文件 *。hcc:必须为每个具体模板参数编译一次的文件。
See Also Compile-Time Dependencies

EDIT2

直接在头文件中写入模板定义,称为包含模型。这样做会增加包含标头的成本。这不仅是因为我们添加了模板的定义,还因为我们包含了代表数千行的标题(,,whatever)。编译重要程序的真实的问题(我们在这里谈论的是数小时的编译)分离模型
Source
最后一个论点:请清除头文件,使其仅包含类声明及其文档。像这样,任何其他程序员都可以快速读取你的头文件:这个类的公共接口是什么,文档是怎么说的。

lymgl2op

lymgl2op2#

模板代码保留在.hh文件中。没有理由将它们分开,尽管将定义放在所有声明之后是一个很好的做法。
当编译器生成模板代码时,它会对其进行标记,以便链接器知道一个编译单元中的模板的示例化(即。即.o文件)与另一个单元中的代码完全相同。它将保留一个并丢弃其余的,而不是用“多重定义的符号”错误来保释。
这对于具有良好模板支持的现代编译器来说是正确的。在GCC的情况下,由于2。8.(我知道,我为gccwww.example写了很多代码 www.example.com 。)

ijxebb2r

ijxebb2r3#

我很失望,没有答案提到C++标准允许你把定义和声明分开。是这样的:

// Foo.h
export template<class T> T f();
// Foo.cpp
#include "Foo.h"

export template<class T> T f()
{
    // blah blah
}

不幸的是,几乎没有编译器支持 export。科莫就是这样的人。
但是,export 在C0x中从C中删除。

ee7vknir

ee7vknir4#

令人惊讶的是,每个人都完全错过了泛型类型的方法。实际上利用唯一的类型占位符。

注意事项

如果你了解链接器/编译器的行为,你需要为这些后果做好准备和计划。
可能是一个好主意,FirstLetter泛化占位符,使它是完全独特的(i。即template <typename OMT>template <typename OLT>

#include <iostream>

template <typename T>
void OutputMessage ( T msg ) {
    std::cout << msg;
}

template <typename C>
void OutputLine ( C msg ) {
    std::cout << msg << std::endl;
}

int main()
{
    std::cout << "Hello World!\n";

    OutputLine("Yello Horld");
    OutputMessage("Wello Horld!\n");
}

相关问题