我应该总是在头文件中定义我的整个模板类吗? 由于某种原因,当你把一个模板类(即一个声明为模板类的东西的类)分成一个 .H./C>和一个文件时,C++似乎不喜欢它,就像你将和任何其他类一样。
这是否意味着在编写模板类时,我应该将其全部写入头文件?C++程序员在这些情况下做什么? 编辑:我知道除了将其全部写入我应该总是在头文件中定义我的整个模板类吗? 由于某种原因,当你把一个模板类(即一个声明为模板类的东西的类)分成一个 .H./C>和一个文件时,C++似乎不喜欢它,就像你将和任何其他类一样。,c++,templates,C++,Templates,这是否意味着在编写模板类时,我应该将其全部写入头文件?C++程序员在这些情况下做什么? 编辑:我知道除了将其全部写入.h文件之外,还有其他方法。但最好的选择是什么?或者最常见的选择是什么 “这是否意味着当编写模板类时,我应该把它全部写在头文件中?C++程序员在这些情况下做什么?” 您所能做的(并且是广泛使用的/流行的做法)是将单独的实现代码输出到特殊的模板实现文件中,这些文件将依次包含在包含声明的模板头中。 在大多数情况下,如果您想隐藏实现细节,而不想将头文件溢出而变大,那么这种技术的好处被认为
.h
文件之外,还有其他方法。但最好的选择是什么?或者最常见的选择是什么
“这是否意味着当编写模板类时,我应该把它全部写在头文件中?C++程序员在这些情况下做什么?”
您所能做的(并且是广泛使用的/流行的做法)是将单独的实现代码输出到特殊的模板实现文件中,这些文件将依次包含在包含声明的模板头中。在大多数情况下,如果您想隐藏实现细节,而不想将头文件溢出而变大,那么这种技术的好处被认为很少,尽管它有它的优点 关键是不要在单独的翻译单元中包含模板定义代码或专门化,这样其他翻译单元(包括模板头文件)就可以直接看到这些代码或专门化 常见的模式是 MyTemplate.h
#if !defined(MYTEMPLATE_H_)
#define MYTEMPLATE_H_
namespace myspace {
template <typename T>
class MyTemplate {
public:
void foo(T value);
};
#include "MyTemplate.tcc"
}
#endif // MYTEMPLATE_H_
class MyClass {
public:
void foo(int);
};
// Violates ODR if MyClass.h is included from different translation units (.cpp files)
void MyClass::foo(int param) {
}
模板版本
template<typename T>
class MyClass {
public:
void foo(T);
};
// Doesn't violate ODR if MyClass.h is included from different translation units
// (.cpp files), since the template parameter isn't instatiated here yet.
template<typename T>
void MyClass<T>::foo(T param) {
}
模板
类MyClass{
公众:
void foo(T);
};
//如果MyClass.h包含在不同的翻译单元中,则不会违反ODR
//(.cpp文件),因为模板参数尚未在此处设置。
模板
void MyClass::foo(T参数){
}
当一个翻译单元实例化类似于MyClass
的内容时,其他安装相同模板签名的翻译单元将使用看到的第一个模板签名
后一个实现部分可以替换为包含该代码的#include“MyClass.impl”
,如果您认为这会严重影响头文件的可读性或可维护性
作为include“MyClass.tcc”技术的一个小缺点,您应该注意到,大多数流行的IDE对此类模板实现文件的语法高亮显示和智能感知处理得很差。通常将模板的定义拆分为另一个文件。这是如此流行,甚至可能是最常见的做法,但我对此并不乐观 我认为这是一种糟糕的做法(而不是将定义放在同一个标题中),原因如下 我在编写代码时的优先事项是(首先最重要):
我看不出将模板定义放在单独的标题中有什么好处,也没有多少成本。C++不介意,您只需在文件中显式实例化模板类型即可帮助编译器找到函数体。@JoachimPileborg我刚刚保留了它,直接将其标记为重复。我同意,但这有着深刻的关联。好吧,4个就足够了吗?如果有人不同意,请投票重新打开。在.inl文件中编写实现,并#将其包含在.h文件的末尾。这样,您就不需要有影响可读性的凌乱的头文件。在某些情况下,如果一个模板仅在一个cpp中使用,则可以在cpp中使用模板实现,但这种情况更为罕见(例如,嵌套的私有模板类或在cpp中显式实例化的特定可用实例化),因此只需将.cpp#包括标头,而不是.cpp#包括标头(其中包含实现)“@AvivCohn”如此简单,而不是.cpp
template<typename T>
class MyClass {
public:
void foo(T);
};
// Doesn't violate ODR if MyClass.h is included from different translation units
// (.cpp files), since the template parameter isn't instatiated here yet.
template<typename T>
void MyClass<T>::foo(T param) {
}