Форум программистов, компьютерный форум CyberForum.ru

Не могу найти ошибку. - C++

Восстановить пароль Регистрация
 
eaglecrazy
1 / 1 / 0
Регистрация: 06.02.2012
Сообщений: 31
18.02.2012, 13:57     Не могу найти ошибку. #1
Добрый день всем! Опять у меня проблемы с моими "любимыми" шаблонами. Есть две шаблонные функции печатающие содержимое списка. Первая для любого типа, вторая для char. В ней возникают такие ошибки:

15/15-06/List.h||In member function ‘void List<T>:rintList() const [with T = char]’:|
15/15-06/List.h|97|error: invalid use of incomplete type ‘struct ListNode<char>’|
15/15-06/List.h|5|error: declaration of ‘struct ListNode<char>’|
15/15-06/List.h|98|error: invalid use of incomplete type ‘struct ListNode<char>’|
15/15-06/List.h|5|error: declaration of ‘struct ListNode<char>’|
||=== Build finished: 4 errors, 0 warnings ===|


Вот код классов и этих функций:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
template<typename T> //строка номер 5 на которую жалуется компилятор
class ListNode;
 
template<typename T>
class List
{
    public:
        List();//
        ~List();//
        void inputFirst(const T &);//
        void deleteFirst();
        void inputLast(const T &);//
        void deleteLast();
        bool isEmpty() const;//
        void printList()const;//
        List<T> & operator=(const List<T> &);
        List<T> & operator+(const List<T> &);
 
    private:
        ListNode<T> *first;
        ListNode<T> *last;
        ListNode<T> *newNode(const T &);//
};
 
template<typename T>
class ListNode
{
    friend class List<T>;
 
    public:
        ListNode()
        {
            next = NULL;
        };
 
    private:
        ListNode *next;
        T data;
};
 
template<>
void List<char>::printList() const
{
    if(isEmpty())
    {
        cout << "List is empty" << endl;
        return;
    }
 
    ListNode<char> *ptr = first;
 
    while(ptr != NULL)
    {
        cout << ptr->data;//строка 97 на которую жалуется компилятор
        ptr = ptr->next;//строка 98 на которую жалуется компилятор
    }
    cout << endl;
}
 
 
template<typename T>
void List<T>::printList() const
{
    if(isEmpty())
    {
        cout << "List is empty" << endl;
        return;
    }
 
    ListNode<T> *ptr = first;
 
    while(ptr != NULL)
    {
        cout << ptr->data << endl;
        ptr = ptr->next;
    }
}
Пожалуйста помогите вычислить ошибку.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.02.2012, 13:57     Не могу найти ошибку.
Посмотрите здесь:

C++ Не могу найти ошибку.
C++ не могу найти ошибку
C++ Не могу найти ошибку!
Не могу найти ошибку C++
Не могу найти ошибку C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Nick Alte
Эксперт С++
1590 / 982 / 115
Регистрация: 27.09.2009
Сообщений: 1,897
Завершенные тесты: 1
18.02.2012, 14:19     Не могу найти ошибку. #2
Лучше сделать ListNode внутренним классом:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<typename T>
class List
{
    class ListNode
    {
        friend class List<T>;
        public:
            ListNode(): next(0) {}
        private:
            ListNode *next;
            T data;
    };
 
    public:
        void printList()const;
 
    private:
        ListNode *first, *last;
        ListNode* newNode(const T &);
};
eaglecrazy
1 / 1 / 0
Регистрация: 06.02.2012
Сообщений: 31
18.02.2012, 19:58  [ТС]     Не могу найти ошибку. #3
Лучше, но я как то не понял про конструктор
C++
1
ListNode(): next(0) {}
как это?

Так как то тоже много ошибок вылезает. А если не делать ListNode внутренним классом? Ошибка то наверняка очень просто исправляется, я так думаю...
HardMorg
2 / 25 / 3
Регистрация: 29.08.2010
Сообщений: 204
18.02.2012, 20:58     Не могу найти ошибку. #4
eaglecrazy,
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <iostream>
 
using namespace std; 
//template<typename T> //строка номер 5 на которую жалуется компилятор
//class ListNode;
 
 
 
template<typename T>
class ListNode {
 //  friend class List<T>;
 
    public:
        ListNode()
        {
            next = NULL;
        };
 
        T getData() {
            return data;
        }
        
        ListNode* getNext() {
            return next;
        }
public:
 
        ListNode *next;
        T data;
};
 
 
template<typename T>
class List
{
    public:
        List() {};//
        ~List() {};//
        void inputFirst(const T &);//
        void deleteFirst();
        void inputLast(const T &);//
        void deleteLast();
        bool isEmpty() const;//
        void printList()const;//
    void printList2(char = 0)const {
        if(this->isEmpty()){
                cout << "List is empty" << endl;
                 return;
            }
 
            ListNode<char> *ptr = first;
 
            while(ptr != NULL)
            {
                cout << ptr->data;//строка 97 на которую жалуется компилятор
                ptr = ptr->next;//строка 98 на которую жалуется компилятор
            }
            cout << endl;
        }
 
        List<T> & operator=(const List<T>&);
        List<T> & operator+(const List<T> &);
 
    private:
        ListNode<T> *first;
        ListNode<T> *last;
        ListNode<T> *newNode(const T &);//
};
 
 
 
template<typename T>
void List<T>::printList() const
{
    if(this->isEmpty())
    {
        cout << "List is empty" << endl;
        return;
    }
 
    ListNode<T> *ptr = first;
 
    while(ptr != NULL)
    {
        cout << ptr->data << endl;
        ptr = ptr->next;
    }
}
Так не пойдет? Понятно что это сырой вариант
я привык всегда реализовывать функции в классе)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#include <iostream>
 
class out_of_range : public std::exception {
 
public:
    out_of_range() { }
};
 
template<class Node, class T>
class iterator {
    
private:
    Node *current;
    
public:
    iterator(Node *node):current(node) { }
    
    void operator++() {
 
        if(!current)
            throw new out_of_range();
 
        current = current->getNext();
    }
 
    bool operator == (iterator const &other) {
 
        return current == other.current;
    }
 
    bool operator !=(iterator const &other) {
        
        return current != other.current;
    }
 
    Node* operator->() {
 
        return current;
    }
};
 
 
template<class T>
class node {
 
private:
    T value;
    node *next;
    node *prev;
public:
    node(T value) {
        next = NULL;
        prev = NULL;
        this->value = value;
    }
 
    node* getNext() {
        return next;
    }
 
    node* getPrev() {
        return prev;
    }
 
    void setPrev(node *n) {
        prev = n;
    }
    void setNext(node *n) {
        next = n;
    }
    T getValue() {
        return value;
    }
};
        
template<class T> 
class list {
 
public:
    typedef iterator<node<T>, T> iterator;
 
private:
    node<T> *root;
 
public:
    list():root(NULL) { };
 
    void push_back(T value) {
 
        if(root) {
 
            node<T> *temp = root;
            while(temp->getNext()) {
                temp = temp->getNext();
            }
            temp->setNext(new node<T>(value));
            temp->getNext()->setPrev(temp);
 
        }else {
            root = new node<T>(value);
        }
 
    }
    
    T pop_back() {
 
        if(!root) 
            throw new out_of_range();
 
        if(!root->getNext()) {
            T value = root->getValue();
            delete root;
            root = NULL;
            return value;
        } else {
 
            node<T> *del = root;
            while(del->getNext()) {
                del = del->getNext();
            }
 
            T value = del->getValue();
            del->getPrev()->setNext(NULL);
            delete del;
            return value;
        }
    }
 
    void push_front(T value) {
 
        if(!root) {
            root = new node<T>(value);
        } else {
 
            node<T> *newnode = new node<T>(value);
            newnode->setNext(root);
            root->setPrev(newnode);
            root = newnode;
        }
    }
 
    T pop_front() {
 
        if(!root) 
            throw new out_of_range();
 
        if(!root->getNext()) {
            T value = root->getValue();
            delete root;
            root = NULL;
            return value;
        }else {
 
            T value = root->getValue();
            node<T> *newroot = root->getNext();
            delete root;
            root = newroot;
            root->setPrev(NULL);
            return value;
        }
    }
 
        
    iterator begin() {
 
        return iterator(root);
    }
 
    iterator end() {
        return iterator(NULL);
    }
 
    ~list() {
 
        while(root) {
 
            node<T> *del = root;
            root = root->getNext();
            delete del;
        
        }
    }
 
};
 
 
 void main() {
 
 
    list<int> integer;
 
    integer.push_back(1);
    integer.push_back(2);
    integer.push_back(3);
    integer.push_back(4);
    integer.push_front(5);
    integer.push_front(6);
 
    std::cout << integer.pop_back() << std::endl;
    std::cout << integer.pop_back() << std::endl;
    std::cout << integer.pop_front() << std::endl;
    std::cout << integer.pop_back() << std::endl;
    std::cout << integer.pop_back() << std::endl;
    
 
    for(list<int>::iterator it = integer.begin(); it != integer.end(); it++)
        std::cout << it->getValue() << std::endl;
 
}
я тоже пытался делать свой лист может поможет
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
template<>
void List<char>::printList() const
{
    if(isEmpty())
    {
        cout << "List is empty" << endl;
        return;
    }
 
    ListNode<char> *ptr = first;
 
    while(ptr != NULL)
    {
        cout << ptr->data;//строка 97 на которую жалуется компилятор
        ptr = ptr->next;//строка 98 на которую жалуется компилятор
    }
    cout << endl;
}
 
 
template<typename T>
void List<T>::printList() const
{
    if(isEmpty())
    {
        cout << "List is empty" << endl;
        return;
    }
 
    ListNode<T> *ptr = first;
 
    while(ptr != NULL)
    {
        cout << ptr->data << endl;
        ptr = ptr->next;
    }
}
по моему функции так не перегружаются, должны отличатся типами параметров.
Даже не понятно зачем тебе такая функция если первая тоже самое
eaglecrazy
1 / 1 / 0
Регистрация: 06.02.2012
Сообщений: 31
18.02.2012, 22:04  [ТС]     Не могу найти ошибку. #5
Цитата Сообщение от HardMorg Посмотреть сообщение
Так не пойдет? Понятно что это сырой вариант
Попробую без дружественного класса сделать. Но всё же очень хотелось бы понять, почему так не работает...


Цитата Сообщение от HardMorg Посмотреть сообщение
я тоже пытался делать свой лист может поможет
Спасибо. Разбираться с чужим кодом... мне бы со своим разобраться



Цитата Сообщение от HardMorg Посмотреть сообщение
по моему функции так не перегружаются, должны отличатся типами параметров.
Даже не понятно зачем тебе такая функция если первая тоже самое
Ну одна функция элемент класса List<T>, другая List<char>, это две большие разницы насколько я понимаю. А функция для List<char> должна печатать строчки, вместо того что бы печатать всё остальное в столбик. Вот.

Добавлено через 23 минуты
Вот я избавился от дружественности, всё заработало. Но хотелось бы разобраться, почему не работает так, как я написал изначально???
AzaKendler
 Аватар для AzaKendler
214 / 116 / 9
Регистрация: 30.05.2011
Сообщений: 1,772
18.02.2012, 22:10     Не могу найти ошибку. #6
Цитата Сообщение от eaglecrazy Посмотреть сообщение
template<typename T> //строка номер 5 на которую жалуется компилятор
class ListNode;
а самое простое пробовал? вынести все определение листноды над лист?

в общем на самый верх просто определение

C++
1
template<typename T> class List;
это чтобы в листноде не ругалось на friend.

далее полное определение листноды, и только потом сам лист

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

а в самой листноде просто прописано, мол класс лист - друг. и все никакого использования.
поэтому на самый верх объявление прототипа листа, далее полное определение листноды, потом лист

попробуй
HardMorg
2 / 25 / 3
Регистрация: 29.08.2010
Сообщений: 204
18.02.2012, 22:17     Не могу найти ошибку. #7
eaglecrazy,
как по моему просто ты не пергрузил функции вот и все, сам подумай вот шаблон который принимает любой тип и даже чар, то есть я не могу обьяснить, ну а как тогда описать эти 2 методы внутри в классе что бы была перегрузка?)))
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.02.2012, 22:33     Не могу найти ошибку.
Еще ссылки по теме:

C++ Не могу найти ошибку
C++ Не могу найти ошибку
C++ Не могу найти ошибку

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
eaglecrazy
1 / 1 / 0
Регистрация: 06.02.2012
Сообщений: 31
18.02.2012, 22:33  [ТС]     Не могу найти ошибку. #8
Цитата Сообщение от AzaKendler Посмотреть сообщение
а самое простое пробовал? вынести все определение листноды над лист?
Попробовал, вставил, подключил листноду перед листом и всё заработало! Ура-ура! Огромное спасибо!

Теперь двумя способами сделал -> польза мне


Цитата Сообщение от HardMorg Посмотреть сообщение
ну а как тогда описать эти 2 методы внутри в классе что бы была перегрузка?)))
Незнаю :/ Наверно поэтому лучше такие вещи вне класса записывать, явно указывая для какого класса эта функция.
Yandex
Объявления
18.02.2012, 22:33     Не могу найти ошибку.
Ответ Создать тему
Опции темы

Текущее время: 00:16. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru