//Version 1
template <typename T>
class Node<T> {
private:
T data;
Node *next;
public:
Node(T data) {
this->data = data;
this->next = NULL;
}
};
//Version 2
template <typename T>
class Node {
private:
T data;
Node *next;
public:
Node(T);
};
template <typename T>
Node<T>::Node(T val) {
data = val;
next = NULL;
}
我对使用版本1创建类与使用版本2创建类之间的区别感到困惑。首选版本1或版本2是什么?
答案 0 :(得分:3)
首先,第二个根本就不编译。正确的语法是
template <typename T>
Node<T>::Node(T val) { // note the <T> part
但除此之外,从编译器的角度来看没有区别。
然而,从程序员的角度来看,存在差异。通常认为通过实施污染类声明是错误的。另一个想要使用你的代码的程序员(当你转移到项目的另一部分时甚至是你自己)应该能够在不查看实现的情况下理解你的代码所做的事情,因此你不应该用实现细节来污染类声明。
更好的做法是将代码分成单独的.cpp
文件,将#include
.cpp
文件分隔到标题中(后者是模板化类的要求,除非您使用显式实例化)。 (有时,.cpp
以外的扩展名(例如.tpp
)用于此目的,但无论如何该文件都应包含在标题中。)
另外需要注意的是,您应该坚持构造函数中的成员初始化列表:
template <typename T>
Node::Node(T val): data(val), next(NULL)
{}
答案 1 :(得分:0)
我会使用版本1但没有显式的指针和成员初始化器:
//Version 1'
template <typename T>
class Node {
private:
T data;
Node *next;
public:
Node(T _data) : data(_data), next(0) { }
};
对于版本2,带有“::”的命名空间访问通常用于实现文件(.cc .cpp ...)而不是标题afaik
答案 2 :(得分:0)
正式地说,在第一个版本中,构造函数是内联的,而在第二个版本中则不是。但是对于模板和现代优化编译器,这种差别并不重要:因为它是一个模板,所以定义必须在同一个文件中,并且优化器可能会忽略优化提示,因为它可以自己确定函数何时值得被内联(对于这样一个简单的函数总是如此)。