模板问题

时间:2011-07-04 05:34:38

标签: c++ templates

我有三个文件,我想编译并运行它们,但我不断收到一些错误和警告。结构节点的重新定义< T>。我对模板知之甚少,但这对我来说是正确的。而且,我花了很多时间试图弄清楚什么是错的。谢谢。

//mystack.h
#ifndef MYSTACK_H
#define MYSTACK_H

template <class T>
struct Node
{
    T info;
    T *next;
};

template <class T>
class MyStack
{
private: 
    struct Node<T> *top;
public:

    void Push(T item);

    void Pop();

    int Top();

    void Print();  
};

#endif

//mystack.cpp
#include <iostream>
#include "mystack.h"

template <class T>
struct Node
{   
    T info;
    T* next; 
};

template <class T>
class MyStack
{
private: 
    struct Node<T>* top;

public:  
    void Push(T item) 
    {
        if(top == NULL)
        {
            top = new( struct Node<T> );
            top->info = item;
            top->next = NULL;
        } else 
        {
            Node<T>* temp;
            temp = top;
            top = new( struct Node<T> );
            top->info = item;
            top->next = temp;
        }
    }

    void Pop()
    {
        if( top == NULL )
        {
        } else 
        {    
            Node<T>* temp;
            temp = top->next;
            delete top;
            top = temp;
        }
    }

    int Top()
    {
        return top; 
    }

    void Print() 
    {   
        if(top != NULL)
        {
            Node<T>* temp;
            temp = top;
            while(temp != NULL)
            {
                std::cout << temp << std::endl;
                temp = temp->next;
            }
        }
    }   
};

3 个答案:

答案 0 :(得分:2)

你在列表中犯的一个错误就是你重新定义了这个结构。

这个定义:

template <class T>
struct Node
{   
    T info;
    T* next; 
};

这个定义在两个清单中完成。

编辑:第二件事是你的类方法实现看起来不正确。如果您在使用模板时尝试不拆分cpp和头文件,那么您将获得最大的成功。

答案 1 :(得分:0)

如果您正在设计一个类而不是模板,那么您所做的就是错误,因为您正在重新定义类型。

但是既然你正在编写模板,那么你早就错了:你不能单独编译模板。

C ++编译模型的简要指针:

// Definition of Node
template<typename T>
struct Node {
    T info;
    T* next; // shouldn't that be a Node*?
};

// Definition of MyStack
template <typename T>
class MyStack
{
private: 
    Node<T> *top;
public:

    // Declarations, but not definitions, of the Mystack function members.
    void Push(T item);
    void Pop();
    int Top();
    void Print();  
};

// Example definition of MyStack::Push
template<typename T>
void
MyStack<T>::Push(T item)
{
    // as before
}

类型定义通常出现在标题中(如果它们要在不同的TU中重用),并且正在执行包含保护。守卫在这里,因为每个TU最多只能出现一次定义。 不要手动重复类型定义(例如,在源文件中)。这是错误的,因为它应该是:没有人想要复制粘贴错误。

函数成员 definitions 通常出现在源文件中,除非它们是模板的成员。在后一种情况下,将它们放在标题中更简单(它们也不必是内联的)。

您可以在SO,书籍或互联网上的其他地方了解编译模型的详细信息。搜索“模板定义”或“一个定义规则”(或ODR)可以提供帮助。

答案 2 :(得分:0)

首先,在标题中,从'struct Node * top;'行中删除'struct'。在C ++中,结构几乎与类相同,唯一的区别是结构成员默认是公共的,而类成员默认是私有的。您不需要使用struct关键字为结构类型添加序列,例如直接C。

其次,你的CPP是错的。模板在需要时由编译器实例化,因此它们不会存在于CPP文件中以便像正常情况一样编译到对象中(除了模板特化)。您可以将模板定义放在HPP本身中,或者更好的通用解决方案是使用IPP文件,即

// mystack.ipp
#ifndef MYSTACK_IPP
#define MYSTACK_IPP

#include "mystack.h"
#include <iostream>

template <class T>
void MyStack<T>::Push(T item) 
{
    if(top == NULL)
    {
        top = new( struct Node<T> );
        top->info = item;
        top->next = NULL;
    } else 
    {
        Node<T>* temp;
        temp = top;
        top = new( struct Node<T> );
        top->info = item;
        top->next = temp;
    }
}

template <class T>
void MyStack<T>::Pop()
{
    if( top == NULL )
    {
    } else 
    {    
        Node<T>* temp;
        temp = top->next;
        delete top;
        top = temp;
    }
}

template <class T>
int MyStack<T>::Top()
{
    return top; 
}

template <class T>
void MyStack<T>::Print() 
{   
    if(top != NULL)
    {
        Node<T>* temp;
        temp = top;
        while(temp != NULL)
        {
            std::cout << temp << std::endl;
            temp = temp->next;
        }
    }
}   
#endif

然后在任何使用MyStack实现的文件中'#include“mystack.ipp”'