什么是以下两个C ++类之间的区别?

时间:2015-05-05 19:12:53

标签: c++ class

    //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是什么?

3 个答案:

答案 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)

正式地说,在第一个版本中,构造函数是内联的,而在第二个版本中则不是。但是对于模板和现代优化编译器,这种差别并不重要:因为它是一个模板,所以定义必须在同一个文件中,并且优化器可能会忽略优化提示,因为它可以自己确定函数何时值得被内联(对于这样一个简单的函数总是如此)。