Беда с шаблонами - PullRequest
       1

Беда с шаблонами

0 голосов
/ 04 июля 2011

У меня есть три файла, и я хочу скомпилировать и запустить их, но я продолжаю получать некоторые ошибки и предупреждения.Переопределение struct Node .Я не знаю много о шаблонах, но мне это кажется правильным.И я потратил много времени, пытаясь понять, что не так.Благодарю.

//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 ]

2 голосов
/ 04 июля 2011

Одна ошибка, которую вы допустили в списках, заключается в том, что вы переопределяете эту структуру, как она говорит.

Это определение:

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

Это определение сделано в обоих списках.

Edit: Второе, что ваша реализация метода класса выглядит неправильно. Вы добьетесь наибольшего успеха, если попытаетесь не разбивать файлы cpp и header при использовании шаблонов.

0 голосов
/ 04 июля 2011

Во-первых, в заголовке удалите «struct» из строки «struct Node * top;».В 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

Затем «#include« mystack.ipp »» в любом файле, который используетреализация MyStack

0 голосов
/ 04 июля 2011

Если бы вы разрабатывали класс вместо шаблона, то, что вы делаете, было бы неправильно, потому что вы переопределяли типы.

Но поскольку вы пишете шаблоны, вы ошибаетесь раньше: вы не можете отдельно скомпилировать шаблоны.

Краткий указатель на модель компиляции 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) может помочь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...