0

原谅冗长的代码包含,但我通常在发布有关问题时遇到问题,包括正确的内容。

我花了大约 2 个小时阅读模板类和故障排除,但我显然错过了一些非常重要的东西。

我一直在研究 Set 数据结构以提高我的编码效率(我在旅行中发布了各种问题),我最近完成了它。我现在已经开始(显然很繁重)将它变成一个模板类!然而,我在编译它时遇到了数百行错误。

我有一种感觉,所有这些都源于我反复犯的一个错误,所以我只包括了大约 1/5 的错误。我花了大约 2 个小时阅读模板类和故障排除,但我显然错过了一些非常重要的东西。

再次,我为包含我的整个文件而道歉。

谢谢!

myset.h:

// a string set implemented with doubly and head sentinal linked list

#ifndef SET_H
#define SET_H
#include <iostream>
#include <string>

using namespace std;

template< class T >
class Set{
private:
    struct Elem {
        T info;
        Elem *prev, *next;
    };
    Elem *_head, *_tail;
    int _size;

    void copyCode(const Set & v);
    // common code for copy constructor and assignment
    void destructCode();
    // common code for deallocation
    ostream& dump(ostream& out, const Set &v);
    // output set elements

public:
    Set();
    // constructs empty set

    Set(const Set &rhs);
    // copy constructor

    ~Set();
    // destructor

    Set& operator=(const Set &rhs);
    // assignment operator

    bool insert( T );
    // insert an int into the set; return true if successful

    bool erase( T );
    // remove an int from the set; return true if successful

    void clear();
    // remove all elements from set

    int size() const { return _size; }
    // return size of the set

    bool find( T ) const;
    // return true if an element is found; false otherwise

    class Iterator{
    private:
    Elem * _cur;

    public:
        Iterator(){}
        explicit Iterator( Elem* );

    Iterator operator++( int );
    Iterator operator++();
    Iterator operator--( int);
    Iterator operator--();

    bool operator==( const Iterator& rhs );
    bool operator!=( const Iterator& rhs );

    T& operator*();

    };

    Iterator begin() const; 
    Iterator end() const;

    friend ostream& operator<< <>(ostream&, Set<T>&);


};

template< class Y >
bool operator==(const Set<T>&, const Set<T>&);

template< class Y >
bool operator!=(const Set<T>&, const Set<T>&);

template< class Y >
Set operator&(const Set<T>&, const Set<T>&);

template< class Y >
Set operator|(const Set<T>&, const Set<T>&);

#include "myset.cpp"
#endif

myset.cpp:

#include <iostream>
#include <string>
#include "myset.h"

using namespace std;


// common code for copy constructor and assignment
void Set<T>::copyCode(const Set<T> & v){

    Elem * p1 = 0;//current
    Elem * p2 = 0;//next
    Elem * p3 = 0;

    if( v._head == 0 )
        _head = _tail = 0;

    else
    {
        _head = new Elem;
        _head -> info = v._head -> info;
    _head -> prev = 0;

        p1 = p2 = _head;
        p3 = v._head -> next;
    }

    while( p3 != v._tail )
    {
        p1 -> next = new Elem;
        p1 = p1 -> next;
        p1 -> info = p3 -> info;
    p1 -> prev = p2;

    p2 = p1;
        p3 = p3 -> next;
    }

    _tail = new Elem;
    _tail -> info = v._tail -> info;
    _tail -> next = 0;
    _tail -> prev = p1;

    p1 -> next = _tail;

    _size = v._size;
}


// common code for deallocation
void Set<T>::destructCode(){

    Elem * p1 = _head;
    Elem * p2 = _head -> next;

    while( p2 ){

    delete p1;
    p1 = p2;
    p2 = p2 -> next;

    }

    delete p1;

    _head = _tail = 0;
    _size = 0;
}


// output set elements
template< class T >
ostream& Set<T>::dump(ostream& out, const Set<T> &v){

    Elem * temp;
    temp = v._head -> next;

    while( temp != v._tail){

    out << temp -> info << " ";
    temp = temp -> next;

    }

    return out;
}


template< class T >
Set<T>::Set(){

    _head = new Elem;
    _tail = new Elem;

    _head -> info = "";
    _head -> next = _tail;
    _head -> prev = 0;

    _tail -> info = "";
    _tail -> next = 0;
    _tail -> prev = _head;

    _size = 0;
}


//Copy Constructor
template< class T >
Set<T>::Set(const Set<T> &rhs){

    copyCode( rhs );
}


//Destructor
template< class T >
Set<T>::~Set(){

    destructCode();
}


//Assignment Operator
template< class T >
Set<T>& Set<T>::operator=(const Set<T> &rhs){

    //Avoid self assignment
    if( this != &rhs ){

    destructCode();
    copyCode( rhs );

    }
    return *this;
}


// insert an int into the set; return true if successful
template< class T >
bool Set<T>::insert( T val ){

    if( !find ( val ) ){
        Elem * temp = new Elem;
        temp -> info = val;

        temp -> prev = _head;
        temp -> next = _head -> next;

        _head -> next -> prev = temp;
    _head -> next = temp;
        _size++;

    return true;
    }

    return false;
}

// remove an int from the set; return true if successful
template< class T >
bool Set<T>::erase( T val ){

    Elem * temp = _head -> next;

    while ( temp && temp != _tail ){

        //Empty Set
        if( temp == _tail )
        return false;

        if( temp -> info == val ){

        temp -> prev -> next = temp -> next;
        temp -> next -> prev = temp -> prev;

        delete temp;
        _size--;
        return true;
        }

        temp = temp -> next;
    }

    return false;
}


// remove all elements from set
template< class T >
void Set<T>::clear(){

    Elem * p1 = _head -> next;
    Elem * p2 = p1 -> next;;

    while( p2 ){

        delete p1;
        p1 = p2;
        p2 = p2 -> next;

    }

    _head -> next = _tail;
    _head -> prev = 0;

    _tail -> next = 0;
    _tail -> prev = _head;

    _size = 0;
}


// return true if an element is found; false otherwise
template< class T >
bool Set<T>::find( T val ) const{

    Elem * temp = _head;

    while( temp ){

    if( temp -> info == val )
        return true;

    else
        temp = temp -> next;
    }

    return false;
}


template< class T >
ostream& operator<< (ostream& out , Set<T>& s ){

    s.dump( out , s );
    return out;
}



//Iterator class
///////////////


//Pass head sentinel of Set.
template< class T >
Set<T>::Iterator::Iterator( Elem * e ){

    _cur = e;

}


//Member prefix
template< class T >
Set<T>::Iterator Set<T>::Iterator::operator++(){

    return Iterator(_cur = _cur -> next);
}


//Member postfix
template< class T >
Set<T>::Iterator Set<T>::Iterator::operator++( int ){

    Elem * temp = _cur;
    _cur = _cur -> next;

    return Iterator(temp);
}


//Member prefix
template< class T >
Set<T>::Iterator Set<T>::Iterator::operator--(){

    return Iterator(_cur = _cur -> prev);
}


//Member postfix 
template< class T >
Set<T>::Iterator Set<T>::Iterator::operator--( int ){

    Elem * temp = _cur;
    _cur = _cur -> prev;

    return Iterator( temp );
}

template< class T > 
T& Set<T>::Iterator::operator*(){

    return _cur -> info;
}


template< class T >
Set<T>::Iterator Set<T>::begin() const{

    return Iterator( _head -> next );
}


template< class T > 
Set<T>::Iterator Set<T>::end() const{

    return Iterator( _tail );
}


template< class T >
bool Set<T>::Iterator::operator==( const Set<T>::Iterator& rhs ){

    return this -> _cur->info == rhs._cur->info;
}


template< class T >
bool Set<T>::Iterator::operator!=( const Set<T>::Iterator& rhs ){

    return this -> _cur->info != rhs._cur->info;
}


template< class T >
bool operator==(const Set<T>& s1 , const Set<T>& s2 ){

    Set<T>::Iterator lit = s1.begin();
    Set<T>::Iterator lit = s2.begin();

    while( lit != lSet.begin() ){

    if( s2.find( *lit )
        lit++;
    else
        return false;
    }

    while( rit != rSet.begin() ){

        if( s1.find( *rit )  
            rit++;
        else
            return false;
    }

    return true;
}


template< class T >
bool operator!=(const Set<T>& s1 , const Set<T>& s2 ){

    Set<T>::Iterator lit = s1.begin();
    Set<T>::Iterator lit = s2.begin();

    while( lit != lSet.begin() ){

        if( s2.find( *lit )  
            lit++;
        else
            return true;
    }

    while( rit != rSet.begin() ){

        if( s1.find( *rit )
            rit++;
        else
            return true;
    }

    return false;

}


//Intersection
template< class T >
Set<T> operator&(const Set<T>& lSet , const Set<T>& rSet ){

    Set<T>::Iterator lit = lSet.begin();
    Set<T> temp;    

    while( lit != lSet.end() ){

    if( rSet.find( *lit ) )
        temp.insert( *lit );

    lit++;
    }
    return temp;
}

//Union
template< class T >
Set<T> operator|(const Set<T>& lSet, const Set<T>& rSet ){

    Set<T>::Iterator lit = lSet.begin();
    Set<T>::Iterator rit = rSet.begin();

    Set<T> temp;

    while( lit != lSet.end() ){
    temp.insert( *lit );
    lit++;
    }

    while( rit != rSet.end() ){
        temp.insert( *rit );
    rit++;
    }

    return temp;
}

错误(在 g++ -g myset.cpp 之后):

bash-4.2$ g++ -g myset.cpp mysettest.cpp 
In file included from myset.cpp:3:0:
myset.h:84:27: error: ‘T’ was not declared in this scope
myset.h:84:28: error: template argument 1 is invalid
myset.h:84:42: error: ‘T’ was not declared in this scope
myset.h:84:43: error: template argument 1 is invalid
myset.h:84:45: error: ‘bool operator==(const int&, const int&)’ must have an argument of class or enumerated type
myset.h:87:27: error: ‘T’ was not declared in this scope
myset.h:87:28: error: template argument 1 is invalid
myset.h:87:42: error: ‘T’ was not declared in this scope
myset.h:87:43: error: template argument 1 is invalid
myset.h:87:45: error: ‘bool operator!=(const int&, const int&)’ must have an argument of class or enumerated type
myset.h:90:1: error: invalid use of template-name ‘Set’ without an argument list
myset.h:93:1: error: invalid use of template-name ‘Set’ without an argument list
In file included from myset.h:95:0,
                 from myset.cpp:3:
myset.cpp:9:10: error: ‘T’ was not declared in this scope
myset.cpp:9:11: error: template argument 1 is invalid
myset.cpp:9:33: error: ‘T’ was not declared in this scope
myset.cpp:9:34: error: template argument 1 is invalid
myset.cpp: In function ‘void copyCode(const int&)’:
myset.cpp:11:5: error: ‘Elem’ was not declared in this scope
myset.cpp:11:12: error: ‘p1’ was not declared in this scope
myset.cpp:12:12: error: ‘p2’ was not declared in this scope
myset.cpp:13:12: error: ‘p3’ was not declared in this scope
myset.cpp:15:11: error: request for member ‘_head’ in ‘v’, which is of non-class type ‘const int’
myset.cpp:16:9: error: ‘_head’ was not declared in this scope
myset.cpp:16:17: error: ‘_tail’ was not declared in this scope
myset.cpp:20:9: error: ‘_head’ was not declared in this scope
myset.cpp:20:21: error: expected type-specifier before ‘Elem’
myset.cpp:20:21: error: expected ‘;’ before ‘Elem’
myset.cpp:21:27: error: request for member ‘_head’ in ‘v’, which is of non-class type ‘const int’
myset.cpp:25:16: error: request for member ‘_head’ in ‘v’, which is of non-class type ‘const int’
myset.cpp:28:20: error: request for member ‘_tail’ in ‘v’, which is of non-class type ‘const int’
myset.cpp:30:26: error: expected type-specifier before ‘Elem’
myset.cpp:30:26: error: expected ‘;’ before ‘Elem’
myset.cpp:39:5: error: ‘_tail’ was not declared in this scope
myset.cpp:39:17: error: expected type-specifier before ‘Elem’
myset.cpp:39:17: error: expected ‘;’ before ‘Elem’
myset.cpp:40:23: error: request for member ‘_tail’ in ‘v’, which is of non-class type ‘const int’
myset.cpp:46:5: error: ‘_size’ was not declared in this scope
myset.cpp:46:15: error: request for member ‘_size’ in ‘v’, which is of non-class type ‘const int’
myset.cpp: At global scope:
myset.cpp:51:10: error: ‘T’ was not declared in this scope
myset.cpp:51:11: error: template argument 1 is invalid
myset.cpp: In function ‘void destructCode()’:
myset.cpp:53:5: error: ‘Elem’ was not declared in this scope
myset.cpp:53:12: error: ‘p1’ was not declared in this scope
myset.cpp:53:17: error: ‘_head’ was not declared in this scope
myset.cpp:54:12: error: ‘p2’ was not declared in this scope
myset.cpp:58:9: error: type ‘&lt;type error>’ argument given to ‘delete’, expected pointer
myset.cpp:64:12: error: type ‘&lt;type error>’ argument given to ‘delete’, expected pointer
myset.cpp:66:13: error: ‘_tail’ was not declared in this scope
myset.cpp:67:5: error: ‘_size’ was not declared in this scope
myset.cpp: At global scope:
myset.cpp:256:1: error: need ‘typename’ before ‘Set<T>::Iterator’ because ‘Set<T>’ is a dependent scope
myset.cpp:264:1: error: need ‘typename’ before ‘Set<T>::Iterator’ because ‘Set<T>’ is a dependent scope
myset.cpp:275:1: error: need ‘typename’ before ‘Set<T>::Iterator’ because ‘Set<T>’ is a dependent scope
myset.cpp:283:1: error: need ‘typename’ before ‘Set<T>::Iterator’ because ‘Set<T>’ is a dependent scope
myset.cpp:299:1: error: need ‘typename’ before ‘Set<T>::Iterator’ because ‘Set<T>’ is a dependent scope
myset.cpp:306:1: error: need ‘typename’ before ‘Set<T>::Iterator’ because ‘Set<T>’ is a dependent scope
myset.cpp: In function ‘bool operator==(const Set<T>&, const Set<T>&)’:
myset.cpp:329:5: error: need ‘typename’ before ‘Set<T>::Iterator’ because ‘Set<T>’ is a dependent scope
myset.cpp:329:22: error: expected ‘;’ before ‘lit’
myset.cpp:330:5: error: need ‘typename’ before ‘Set<T>::Iterator’ because ‘Set<T>’ is a dependent scope
4

2 回答 2

4

类模板的成员函数定义应该这样定义:

    template<typename T> // <== MIND THIS!
    void Set<T>::copyCode(const Set<T> & v) {
        // ...
    }

你忘记了这个template<typename T>部分。此外,您不能将类模板的成员函数定义委托给单独的.cpp文件。除非您提供显式实例化,否则链接器最终会抱怨未解析的引用。

于 2013-03-21T00:07:11.507 回答
0

第一条错误消息在myset.h; 我没有计算行数,但它可能在这里:

template< class Y >
bool operator==(const Set<T>&, const Set<T>&);

The code says the the template argument type is named Y, but the declarations of Set use T. Once you fix those, as @AndyProwl says, you need to define the member function in myset.cpp properly.

You've also got a circular include. myset.h has a #include that pulls in myset.cpp, and myset.cpp has a #include that pulls in myset.h. Get rid of the one in myset.cpp. Oh, and get rid of using namespace std;.

于 2013-03-21T00:32:03.093 回答