模板有问题

Trouble with templates

本文关键字:有问题      更新时间:2023-10-16

我有三个文件,我想编译并运行它们,但我一直收到一些错误和警告。结构节点的重新定义<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;
            }
        }
    }   
};

您在清单中犯的一个错误是,您按照它所说的重新定义了这个结构。

这就是定义:

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

这两个清单中都有这个定义。

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

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

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

关于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的定义最多只能出现一次。不要手动重复类型定义(例如,在源文件中(。这是错误的,因为它应该是:没有人想要复制-粘贴错误。

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

您可以在SO、书籍或互联网上的其他地方了解编译模型的详细信息。搜索"模板定义"或"一个定义规则"(或ODR(可能会有所帮助。

首先,在头中,从"struct-Node*top;"行中删除"struct"。在C++中,结构与类几乎相同,唯一的区别是结构成员默认为公共成员,类成员默认为私有成员。您不需要像在direct C.中那样在结构类型前面加struct关键字

第二,你的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 实现的文件中包含"mystack.ipp">