【问题标题】:Member functions of a templated class, that take a template type as argument模板类的成员函数,以模板类型作为参数
【发布时间】:2011-07-06 05:27:36
【问题描述】:

我有一个节点结构和堆栈类。当我将“void Push(T data)”的定义放在类定义之外时,我得到:

error: 'template<class T> class Stack' used without template parameters

但是当我把它放在类定义中时它工作正常。
代码如下:

template <class T>
struct Node
{
    Node(T data, Node <T> * address) : Data(data), p_Next(address) {}
    T Data;
    Node <T> * p_Next;
};

template <class T> 
class Stack
{
public:

    Stack() : size(0) {}
    void Push(T data);
    T Pop();

private:
    int size;
    Node <T> * p_first;
    Node <T> * p_last;  
};

Push(T data) 的实现是:

void Stack::Push(T data)
{
    Node <T> * newNode;   

    if(size==0)
        newNode = new Node <T> (data, NULL);
    else
        newNode = new Node <T> (data, p_last);

    size++;
    p_last = newNode;
}

编辑:解决方案有效,只是现在每当我尝试调用函数时都会出现链接错误。

Stack<int>::Pop", referenced from   
_main in main.o   
symbol(s) not found.

除非定义在 Stack.h 而不是 Stack.cpp

【问题讨论】:

    标签: c++ templates function types member


    【解决方案1】:

    你需要再次使用template &lt;class T&gt;(然后再次使用T作为类的模板参数):

    template <class T>
    void Stack<T>::Push(T data)
    {
        Node <T> * newNode;   
    
        if(size==0)
            newNode = new Node <T> (data, NULL);
        else
            newNode = new Node <T> (data, p_last);
    
        size++;
        p_last = newNode;
    }
    

    【讨论】:

    • @user4:你知道我为什么会收到链接错误吗?
    • 这是模板在 C++ 中实现方式的一个不幸的副作用。由于必须在编译时知道参数,因此您不能编译模板代码然后将其他代码链接到它,因为编译器必须知道后续文件中的特定实例化才能为第一个文件创建,但是一旦它得到到后续文件为时已晚。有关完整说明和解决方法,请参阅 parashift.com/c++-faq-lite/templates.html#faq-35.13。
    • @user4: 那么将函数定义与类定义一起放在 Stack.h 中是否被认为是一个合适的解决方案?
    • @Matt 在这种情况下,是的,因为真的没有其他方法可以做到这一点。
    【解决方案2】:

    在类外定义成员函数时,需要在成员函数前添加模板语句...

    template <class T>
    void Stack<T>::Push(T data)
    {
        Node <T> * newNode;   
    
        if(size==0)
            newNode = new Node <T> (data, NULL);
        else
            newNode = new Node <T> (data, p_last);
    
        size++;
        p_last = newNode;
    }
    

    (至少应该和这个差不多)

    【讨论】:

    • 它工作,除了如果定义在 Stack.cpp 中它不会让我调用函数,而如果定义在 Stack.h 中它确实有效。我收到链接错误:“Stack::Pop”,从 main.o 中的 _main 引用未找到符号。但我可以从 Stack.cpp 调用非成员函数。
    • C++ 模板的实际实现要求实现代码位于标头中。这方面的一个例子可以在 C++ 标准库中找到。如果您查看随编译器提供的标准库头文件,您会注意到类模板具有完整的类实现,而不仅仅是方法声明。 -- 底线:将方法定义也放在头文件中;链接器和编译器应该处理其余部分。
    【解决方案3】:

    这是因为当定义在类定义中时,它知道模板参数。如果要将定义放在外面,则需要明确告诉编译器 T 是模板参数...

    template <class T>
    void Stack<T>::Push(T data) {/* code */}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多