Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我应该总是在头文件中定义我的整个模板类吗? 由于某种原因,当你把一个模板类(即一个声明为模板类的东西的类)分成一个 .H./C>和一个文件时,C++似乎不喜欢它,就像你将和任何其他类一样。_C++_Templates - Fatal编程技术网

我应该总是在头文件中定义我的整个模板类吗? 由于某种原因,当你把一个模板类(即一个声明为模板类的东西的类)分成一个 .H./C>和一个文件时,C++似乎不喜欢它,就像你将和任何其他类一样。

我应该总是在头文件中定义我的整个模板类吗? 由于某种原因,当你把一个模板类(即一个声明为模板类的东西的类)分成一个 .H./C>和一个文件时,C++似乎不喜欢它,就像你将和任何其他类一样。,c++,templates,C++,Templates,这是否意味着在编写模板类时,我应该将其全部写入头文件?C++程序员在这些情况下做什么? 编辑:我知道除了将其全部写入.h文件之外,还有其他方法。但最好的选择是什么?或者最常见的选择是什么 “这是否意味着当编写模板类时,我应该把它全部写在头文件中?C++程序员在这些情况下做什么?” 您所能做的(并且是广泛使用的/流行的做法)是将单独的实现代码输出到特殊的模板实现文件中,这些文件将依次包含在包含声明的模板头中。 在大多数情况下,如果您想隐藏实现细节,而不想将头文件溢出而变大,那么这种技术的好处被认为

这是否意味着在编写模板类时,我应该将其全部写入头文件?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对此类模板实现文件的语法高亮显示和智能感知处理得很差。

通常将模板的定义拆分为另一个文件。这是如此流行,甚至可能是最常见的做法,但我对此并不乐观

我认为这是一种糟糕的做法(而不是将定义放在同一个标题中),原因如下

我在编写代码时的优先事项是(首先最重要):

  • 正确性
  • 运行时性能
  • 编译时性能
  • 可维护性/易于阅读
  • 容易写
  • 只要模板定义在同一个标头中,或在标头包含的另一个文件中,第一优先级正确性就不会受到任何影响

    第二优先级运行时性能丝毫不受影响

    第三个优先级编译时性能由于将定义放在单独的文件中而受到负面影响。多少是有争议的。但是,编译器不可能像只打开/关闭一个文件时编译完全相同的代码那样快速地编译X数量的代码并打开/关闭两个文件。我的一个朋友是一个优秀的编译器编写者,他曾经告诉我,我能要求他的编译器做的最慢的事情就是打开一个文件。这是在我们做了和今天一样多的编译时计算之前,但仍然

    第四个优先事项可维护性/易读性相当主观。但在我看来,一个单独的文件会对这个优先级产生负面影响。当我阅读代码时,如果代码都在一个文件中,我通常更容易理解它。当我不得不在文件名或位置不明显的情况下查找文件时,我真的很恼火。当定义被分割成许多文件时,我会更加恼火。就我而言,一个文件优化了这个优先级

    第五个优先事项是易于书写,这也是相当主观的。我看这两种方式都没有什么好处。将所有内容都放在一个文件中非常简单。但是创建一个新文件当然并不困难。在这个优先级上,我给“一个文件方法”一个非常微小的优势

    总而言之,在我的五个优先事项中,最重要的两个,这个决定对我来说绝对没有区别,单独的文件对三个较低的优先事项有很小的负面影响。在3个较低优先级中,最重要的是编译时性能客观上受到了负面影响。无可否认,这两个最低优先级对于它们是否受到积极或消极影响是主观的


    我看不出将模板定义放在单独的标题中有什么好处,也没有多少成本。

    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) {
    }