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

Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined - C++

Восстановить пароль Регистрация
 
Gr1f0nn
82 / 81 / 42
Регистрация: 30.09.2012
Сообщений: 408
17.11.2014, 23:04     Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined #1
Здравствуйте!
Снова возникла небольшая проблема.

Создал шаблонный класс:
box.h
Кликните здесь для просмотра всего текста
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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
#ifndef BOX_H
#define BOX_H
//#include "info.h"
#include <iostream>
#include <cstring>
#include <string>
#include <fstream>
using namespace std;
 
template <typename X> class Box
{
private:
     X *head, *tail;
    int size_;
public:
    Box()
    {
        head = NULL;
        tail = NULL;
        size_ = 0;
    }
 
    ~Box()
    {
        clear();
    }
 
    Box(const Box &x)
    {
        X
                *temp,
                *curr;
        string
                msg,
                nick;
        head = tail = NULL;
        size_ = 0;
        curr = x.head;
        do {
            if(curr->get_type() == "info") {
                msg = curr->get_m();
                temp = new X(msg);
            } else {
                msg = curr->get_m();
                nick = curr->get_n();
                temp = new infoD(msg,nick);
            }
            push_back(temp);
            curr = curr->next;
        } while (curr != NULL);
    }
 
    void push_back(X *x)
    {
        X
                *temp;
        temp = x;
        if (!head) {
            tail = head = temp;
            tail->next = NULL;
            tail->prev = NULL;
            size_ ++;
        } else {
            tail->next = temp;
            temp->prev = tail;
            tail = temp;
            tail->next = NULL;
            size_ ++;
        }
    }
 
    void push_front(X *x)
    {
        X
                *temp;
        temp = x;
        if (!head) {
            tail = head = temp;
            tail->next = NULL;
            tail->prev = NULL;
            size_ ++;
        } else {
            temp->next = head;
            head->prev = temp;
            head = temp;
            size_ ++;
        }
    }
 
    void pop_back()
    {
        X
                *temp;
        if (head) {
            temp = tail;
            tail = temp->prev;
            tail->next = NULL;
            delete temp;
            size_ --;
        }
    }
 
    void pop_front()
    {
        X
                *temp;
        if (head) {
            temp = head;
            head = temp->next;
            head->prev = NULL;
            delete temp;
            size_ --;
        }
    }
 
    void erase(X *p)
    {
        X
                *temp;
        temp = p;
        if (temp == begin()) {
            pop_front();
        } else {
            if (temp == end()) {
                pop_back();
            } else {
                if (temp != begin() && temp != end()) {
                    temp->prev->next = temp->next;
                    temp->next->prev = temp->prev;
                    delete temp;
                    size_--;
                }
        }
    }
    }
 
    int size() const
    {
        return size_;
    }
    X *begin() const
    {
        return head;
    }
    X *end() const
    {
        return tail;
    }
    void read()
    {
        string
                type;
        X
                *temp;
        ifstream fin("data");
        if(fin)
        {
            do
            {
                fin >> type;
                if (type == "info") {
                    temp = new X();
                } else {
                    temp = new infoD();
                }
                fin >> temp;
                push_back(temp);
            }
            while(!fin.eof());
        }
        fin.close();
    }
 
    void save()
    {
        X
                *temp;
        ofstream
                fout("data");
        if (head) {
            temp = head;
            do {
                fout << temp;
                temp = temp->next;
            } while (temp != NULL);
        }
        fout.close();
    }
 
    bool empty()
    {
        if (head) {
            return 0;
        } else {
            return 1;
        }
    }
 
    void clear()
    {
        X
                *temp;
        while(head != NULL)
        {
            temp = head;
            head = head->next;
            delete temp;
        }
        head = tail = NULL;
        size_ = 0;
    }
 
    info *operator[] (int i)
    {
        X
                *temp;
        int
                j;
        if (!empty())
            if (i >= 1 && i <= size()) {
                temp = head;
                for( j=0 ; j<i ; j++ ) {
                    temp = temp->next;
                }
                return temp;
            }
        return NULL;
    }
 
    info *operator() (int i)
    {
        return ((*this)[i]);
    }
 
    Box &operator=(const Box &x)
    {
        X
                *temp,
                *curr;
        string
                msg,
                nick;
        if(this != &x)
        {
            curr = x.head;
            clear();
            do {
                if(curr->get_type() == "info") {
                    msg = curr->get_m();
                    temp = new X(msg);
                } else {
                    msg = curr->get_m();
                    nick = curr->get_n();
                    temp = new infoD(msg,nick);
                }
                push_back(temp);
                curr = curr->next;
            } while (curr != NULL);
        }
        return *this;
    }
 
    friend Box operator+(const Box b,  X *i)
    {
        Box<X> temp;
        temp = b;
        X *p;
        p = i;
        temp.push_back(p);
        return temp;
    }
 
    friend Box operator+( X *i, const Box b)
    {
        return (b + i);
    }
 
    friend Box operator -(Box b, int i)
    {
        Box<X> temp;
        temp = b;
        X *p;
        p = temp.begin();
        int j;
        if (i>=1 && i<=temp.size() ) {
            if (i == 1) {
 
                temp.pop_front();
            } else {
                for(j=0 ; j<i ; j++)
                {
                    p = p->next;
                }
                temp.erase(p);
            }
        }
        return temp;
    }
 
    friend Box operator -(int i, Box b)
    {
        return (b - i);
    }
 
    Box operator+=(X *i)
    {
        push_back(i);
        return *this;
    }
 
    Box operator-=(int i)
    {
        X *p;
        p = begin();
        int j;
        if (i>=1 && i<=size() ) {
            if (i == 1) {
 
                pop_front();
            } else {
                for(j=0 ; j<i ; j++)
                {
                    p = p->next;
                }
                erase(p);
            }
        }
        return *this;
    }
 
    Box &operator--()
    {
        pop_back();
        return *this;
    }
 
    Box operator--(int notused)
    {
        Box<X> temp = *this;
        --(*this);
        return temp;
    }
 
    //friend class Dialog;
};
#endif // BOX_H


Хранить собираюсь базовый класс и наследник:
Кликните здесь для просмотра всего текста
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
template <typename X> class Box;
class info
{
protected:
    string message;
    info *next, *prev;
public:
    info();
    info(string _message);
    info(const info &x);
    ~info();
    void set_message(string _message);
    virtual string get_message();
    virtual string get_info();
    virtual string get_type();
    virtual void set(string _message, string _nick);
    virtual void set_m(string _message);
    friend class Dialog;
   // friend template <typename X> class Box;
    bool operator== (info x);
    bool operator> (info x);
    bool operator< (info x);
    info operator= (info x);
    friend ostream &operator<<(ostream &stream, info *x);
    friend istream &operator>>(istream &stream, info *x);
    info &operator++();
    info operator++(int notused);
    string get_m();
    virtual string get_n();
   // friend Box operator -(Box b, int i); //box + int
   // friend Box operator -(int i, Box b); //int + box
    virtual void operator>>(int i);
    virtual void operator<<(int i);
};
 
class infoD : public info
{
private:
    string nick;
public:
    infoD();
    infoD(string _message, string _nick);
    infoD(const infoD &x);
    ~infoD();
    void set_name(string _message, string _nick);
    virtual void set(string _message, string _nick);
    virtual string get_message();
    virtual void set_m(string _message);
    virtual string get_info();
    virtual string get_type();
    friend class Dialog;
   // friend class Box;
    bool operator== (infoD x);
    bool operator> (infoD x);
    bool operator< (infoD x);
    infoD operator= (infoD x);
    friend ostream &operator<<(ostream &stream, info *x);
    friend istream &operator>>(istream &stream, info *x);
    virtual string get_n();
    //friend Box operator -(Box b, int i); //box + int
   // friend Box operator -(int i, Box b); //int + box
    virtual void operator>>(int i);
    virtual void operator<<(int i);
};


Создаю объект так:
C++
1
Box<info*> ob;
Вроде бы делаю все правильно, как в книгах написано.Также объявляю шаблонный класс и реализацию его функций в одном файле, а все равно, при компиляции, выскакивает ошибка:
ошибка: aggregate 'Box<info*> ob' has incomplete type and cannot be defined
На форуме и в интернете ответа на этот вопрос не нашел, поэтому надеюсь на вашу помощь!

Также есть проблема с выделением памяти в функциях read и operator= под класс наследник (infoD), так как если с info все понятно (пишу, например, temp = new X(...) ), то с наследником проблема. Как это реализовать?

Заранее спасибо!
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
17.11.2014, 23:04     Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined
Посмотрите здесь:

C++ Error: Invalid use of incomplete type
C++ Шаблонный класс, ошибка линковки
Переделать класс в шаблонный класс C++
Шаблонный класс C++
C++ Шаблонный класс
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
DrOffset
6416 / 3790 / 876
Регистрация: 30.01.2014
Сообщений: 6,575
17.11.2014, 23:35     Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined #2
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
template <typename X> class Box;
А где, собственно, реализация шаблона Box-то?
Доступной в единице трансляции реализации нет - это и есть причина ошибки.
Gr1f0nn
82 / 81 / 42
Регистрация: 30.09.2012
Сообщений: 408
18.11.2014, 00:00  [ТС]     Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined #3
DrOffset, Не совсем понял вопрос
Я же реализовал его в box.h, а в info.h написал предварительное объявление класса, чтобы использовать дружественные функции(сейчас они закомментированы чисто для отладки). Или я так не могу написать?
То есть, например, данная запись:
C++
1
2
3
4
5
template <typename X> class box;
class info {
// some code
friend void func(Box x, info* i);  // или надо friend void func(Box<X> x, info* i); ?
}
Не эквивалентна этой записи:
C++
1
2
3
4
5
class box;
class info{
// some code
friend void func(Box x, info* i);
}
?

update: Когда убрал в info эту запись:
C++
1
template <typename X> class Box;
То появилось куча ошибок, а точнее проблемы, вытекающие из одной главной ошибки:
ошибка: expected initializer before '<' token
Пишу так:
C++
1
static Box<info*> ob;
<- ошибка ссылается на эту строчку
Тут я вообще потерялся. Например, со списком я ведь делал также:
C++
1
static list<info*> ob;

Не по теме:

С собственными шаблонами работаю впервые, поэтому извините за, возможно, глупые вопросы

DrOffset
6416 / 3790 / 876
Регистрация: 30.01.2014
Сообщений: 6,575
18.11.2014, 00:10     Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined #4
Gr1f0nn, В месте использования Box должен быть полностью определен. Но по твоему коду не очень понятно где именно ты пишешь вот это:
C++
1
Box<info*> ob;
Проще говоря, ты должен в этом месте подключить оба заголовка: и с Box и с info.

Добавлено через 46 секунд
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
update: Когда убрал в info эту запись
Ее не надо убирать. Нужно в месте использования шаблона обеспечить его полное определение. Вот и все.

Добавлено через 5 минут
Gr1f0nn, По поводу friend, писать надо так:
C++
1
2
3
4
5
6
7
template <typename X> class Box;
 
class info {
// some code
    template <typename X>
    friend void func(Box<X> x, info* i);  
};
или так:
C++
1
2
3
4
5
6
template <typename X> class Box;
 
class info {
// some code
    friend void func(Box<info*> x, info* i);  
};
Gr1f0nn
82 / 81 / 42
Регистрация: 30.09.2012
Сообщений: 408
18.11.2014, 00:14  [ТС]     Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined #5
DrOffset, Кажется понял, о чем вы.
Теперь компилятор на это не ругается ^_^
За разъяснения с дружественными функциями отдельное спасибо!

У меня остался только один вопрос по поводу класса info и производного от него infoD. Так как у меня шаблон задается так:
C++
1
template <typename X> class Box;
объект класса Box создаю так:
C++
1
Box<info*> ob;
Я не могу выделить тем же самым образом память под infoD.
Например, вот в этой функции:
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
    Box(const Box &x)
    {
        X
                *temp,
                *curr;
        string
                msg,
                nick;
        head = tail = NULL;
        size_ = 0;
        curr = x.head;
        do {
            if(curr->get_type() == "info") {
                msg = curr->get_m();
                temp = new X(msg);
            } else {
                msg = curr->get_m();
                nick = curr->get_n();
                temp = new infoD(msg,nick); // ? 
            }
            push_back(temp);
            curr = curr->next;
        } while (curr != NULL);
    }
Как мне написать, что, в данном случае, тип данных infoD является производным от X (info)?
DrOffset
6416 / 3790 / 876
Регистрация: 30.01.2014
Сообщений: 6,575
18.11.2014, 03:45     Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined #6
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
Как мне написать, что, в данном случае, тип данных infoD является производным от X (info)?
Как-то автоматически это сделать нельзя.
Предлагаю следующее. Инстанцировать шаблон, не базовым типом, а производным:
C++
1
Box<infoD>
Кстати почему в твоем варианте ты параметризуешь его типом-указателя, если Х, судя по приведенном коду, должен быть info, а не info* ?
В производном классе завести typedef который будет псевдонимом для базового, например так:
C++
1
2
3
4
5
6
class infoD : public info
{
public:
    typedef info base;
//.......
};
В теле шаблона писать так:
C++
1
2
3
4
5
6
7
                msg = curr->get_m();
                temp = new typename X::base(msg);
            } else {
                msg = curr->get_m();
                nick = curr->get_n();
                temp = new X(msg, nick);
            }
Хотя, честно говоря, мне кажется лучшим решением будет рассказать про свою задачу здесь. Помогут перепроектировать. Когда возникают проблемы, наподобие этой
C++
1
if(curr->get_type() == "info") {
, значит что-то не так в архитектуре.
Gr1f0nn
82 / 81 / 42
Регистрация: 30.09.2012
Сообщений: 408
18.11.2014, 15:43  [ТС]     Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined #7
DrOffset, Спасибо, кажется, начинаю понимать Ваш ход мыслей

Цитата Сообщение от DrOffset Посмотреть сообщение
Кстати почему в твоем варианте ты параметризуешь его типом-указателя, если Х, судя по приведенном коду, должен быть info, а не info* ?
Так как я храню несколько типов данных в одном контейнере, то я должен хранить указатели на эти объекты, поэтому и пишу не info, а info*. Когда делал что-то подобное с библиотечным списком, то делал также :
C++
1
list<info*> ob;
Вот я и подумал, что здесь должно быть тоже самое ^_^

Насчет полной формулировки задачи:
Необходимо создать класс-контейнер, в котором будет храниться пользовательский базовый-класс и класс-наследник. Класс-контейнер реализовать с помощью шаблона.

Вот полный код:
Box.H
Кликните здесь для просмотра всего текста
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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
#ifndef BOX_H
#define BOX_H
//#include "info.h"
#include <iostream>
#include <cstring>
#include <string>
#include <fstream>
using namespace std;
 
template <typename X> class Box
{
private:
    X *head, *tail;
    int size_;
public:
    Box()
    {
        head = NULL;
        tail = NULL;
        size_ = 0;
    }
 
    ~Box()
    {
        clear();
    }
 
   /* Box(const Box &x)
    {
        X
                *temp,
                *curr;
        string
                msg,
                nick;
        head = tail = NULL;
        size_ = 0;
        curr = x.head;
        do {
            if(curr->get_type() == "info") {
                msg = curr->get_m();
                temp = new X(msg);
            } else {
                msg = curr->get_m();
                nick = curr->get_n();
                temp = new infoD(msg,nick);
            }
            push_back(temp);
            curr = curr->next;
        } while (curr != NULL);
    }*/
 
    void push_back(X *x)
    {
        X
                *temp;
        temp = x;
        if (!head) {
            tail = head = temp;
            tail->next = NULL;
            tail->prev = NULL;
            size_ ++;
        } else {
            tail->next = temp;
            temp->prev = tail;
            tail = temp;
            tail->next = NULL;
            size_ ++;
        }
    }
 
    void push_front(X *x)
    {
        X
                *temp;
        temp = x;
        if (!head) {
            tail = head = temp;
            tail->next = NULL;
            tail->prev = NULL;
            size_ ++;
        } else {
            temp->next = head;
            head->prev = temp;
            head = temp;
            size_ ++;
        }
    }
 
    void pop_back()
    {
        X
                *temp;
        if (head) {
            temp = tail;
            tail = temp->prev;
            tail->next = NULL;
            delete temp;
            size_ --;
        }
    }
 
    void pop_front()
    {
        X
                *temp;
        if (head) {
            temp = head;
            head = temp->next;
            head->prev = NULL;
            delete temp;
            size_ --;
        }
    }
 
    void erase(X *p)
    {
        X
                *temp;
        temp = p;
        if (temp == begin()) {
            pop_front();
        } else {
            if (temp == end()) {
                pop_back();
            } else {
                if (temp != begin() && temp != end()) {
                    temp->prev->next = temp->next;
                    temp->next->prev = temp->prev;
                    delete temp;
                    size_--;
                }
        }
    }
    }
 
    int size() const
    {
        return size_;
    }
    X *begin() const
    {
        return head;
    }
    X *end() const
    {
        return tail;
    }
   /* void read()
    {
        string
                type;
        X
                *temp;
        ifstream fin("data");
        if(fin)
        {
            do
            {
                fin >> type;
                if (type == "info") {
                    temp = new X();
                } else {
                    temp = new infoD();
                }
                fin >> temp;
                push_back(temp);
            }
            while(!fin.eof());
        }
        fin.close();
    }*/
 
    void save()
    {
        X
                *temp;
        ofstream
                fout("data");
        if (head) {
            temp = head;
            do {
                fout << temp;
                temp = temp->next;
            } while (temp != NULL);
        }
        fout.close();
    }
 
    bool empty()
    {
        if (head) {
            return 0;
        } else {
            return 1;
        }
    }
 
    void clear()
    {
        X
                *temp;
        while(head != NULL)
        {
            temp = head;
            head = head->next;
            delete temp;
        }
        head = tail = NULL;
        size_ = 0;
    }
 
    X *operator[] (int i)
    {
        X
                *temp;
        int
                j;
        if (!empty())
            if (i >= 1 && i <= size()) {
                temp = head;
                for( j=0 ; j<i ; j++ ) {
                    temp = temp->next;
                }
                return temp;
            }
        return NULL;
    }
 
    X *operator() (int i)
    {
        return ((*this)[i]);
    }
 
   /* Box &operator=(const Box &x)
    {
        X
                *temp,
                *curr;
        string
                msg,
                nick;
        if(this != &x)
        {
            curr = x.head;
            clear();
            do {
                if(curr->get_type() == "info") {
                    msg = curr->get_m();
                    temp = new X(msg);
                } else {
                    msg = curr->get_m();
                    nick = curr->get_n();
                    temp = new infoD(msg,nick);
                }
                push_back(temp);
                curr = curr->next;
            } while (curr != NULL);
        }
        return *this;
    }
*/
    /*friend Box operator+(const Box b,  X *i)
    {
        Box<X> temp;
        temp = b;
        X *p;
        p = i;
        temp.push_back(p);
        return temp;
    }
 
    friend Box operator+( X *i, const Box b)
    {
        return (b + i);
    }*/
 
    friend Box operator -(Box b, int i)
    {
        Box<X> temp;
        temp = b;
        X *p;
        p = temp.begin();
        int j;
        if (i>=1 && i<=temp.size() ) {
            if (i == 1) {
 
                temp.pop_front();
            } else {
                for(j=0 ; j<i ; j++)
                {
                    p = p->next;
                }
                temp.erase(p);
            }
        }
        return temp;
    }
 
    friend Box operator -(int i, Box b)
    {
        return (b - i);
    }
 
    Box operator+=(X *i)
    {
        push_back(i);
        return *this;
    }
 
    Box operator-=(int i)
    {
        X *p;
        p = begin();
        int j;
        if (i>=1 && i<=size() ) {
            if (i == 1) {
 
                pop_front();
            } else {
                for(j=0 ; j<i ; j++)
                {
                    p = p->next;
                }
                erase(p);
            }
        }
        return *this;
    }
 
    Box &operator--()
    {
        pop_back();
        return *this;
    }
 
    Box operator--(int notused)
    {
        Box<X> temp = *this;
        --(*this);
        return temp;
    }
 
    //friend class Dialog;
};
#endif // BOX_H


info.h
Кликните здесь для просмотра всего текста
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
#ifndef INFO_H
#define INFO_H
#include <iostream>
#include <cstring>
#include <string>
//#include <box.h>
using namespace std;
 
template <typename X> class Box;
class info
{
protected:
    string message;
    info *next, *prev;
public:
    info();
    info(string _message);
    info(const info &x);
    ~info();
    void set_message(string _message);
    virtual string get_message();
    virtual string get_info();
    virtual string get_type();
    virtual void set(string _message, string _nick);
    virtual void set_m(string _message);
    friend class Dialog;
    //friend template <typename X> class Box;
    friend class Box<info*>;
    bool operator== (info x);
    bool operator> (info x);
    bool operator< (info x);
    info operator= (info x);
    friend ostream &operator<<(ostream &stream, info *x);
    friend istream &operator>>(istream &stream, info *x);
    info &operator++();
    info operator++(int notused);
    string get_m();
    virtual string get_n();
   // friend Box operator -(Box b, int i); //box + int
   // friend Box operator -(int i, Box b); //int + box
    virtual void operator>>(int i);
    virtual void operator<<(int i);
};
 
class infoD : public info
{
private:
    string nick;
public:
    infoD();
    infoD(string _message, string _nick);
    infoD(const infoD &x);
    ~infoD();
    void set_name(string _message, string _nick);
    virtual void set(string _message, string _nick);
    virtual string get_message();
    virtual void set_m(string _message);
    virtual string get_info();
    virtual string get_type();
    friend class Dialog;
   // friend class Box;
    friend class Box<info*>;
    bool operator== (infoD x);
    bool operator> (infoD x);
    bool operator< (infoD x);
    infoD operator= (infoD x);
    friend ostream &operator<<(ostream &stream, info *x);
    friend istream &operator>>(istream &stream, info *x);
    virtual string get_n();
    //friend Box operator -(Box b, int i); //box + int
   // friend Box operator -(int i, Box b); //int + box
    virtual void operator>>(int i);
    virtual void operator<<(int i);
};
 
#endif // INFO_H
Gr1f0nn
82 / 81 / 42
Регистрация: 30.09.2012
Сообщений: 408
18.11.2014, 15:44  [ТС]     Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined #8
info.cpp
Кликните здесь для просмотра всего текста
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
#include "info.h"
#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
//info
 
info::info()
{
    message = "";
}
 
info::info(string _message)
{
    message = _message;
}
 
info::~info()
{
 
}
 
string info::get_info()
{
    return " " + message;
}
 
void info::set_message(string _message)
{
    message = _message;
}
 
string info::get_message()
{
    return string("Message: ") + message;
}
 
 
 
string info::get_type()
{
    return "info";
}
 
void info::set(string _message, string _nick)
{
 
}
 
void info::set_m(string _message)
{
    message = _message;
}
 
bool info::operator <(info x)
{
    if (message < x.message) return 1;
    else return 0;
}
 
bool info::operator >(info x)
{
    if (message > x.message) return 1;
    else return 0;
}
 
bool info::operator ==(info x)
{
    if (message == x.message) return 1;
    else return 0;
}
 
info& info::operator++()
{
    for (string::iterator p = message.begin() ; p != message.end() ; p++) {
        *p = toupper(*p);
    }
    return *this;
}
 
info info::operator++(int notused)
{
    info *temp;
    temp = this;
    ++*this;
    return *temp;
}
 
string info::get_m()
{
    return message;
}
 
string info::get_n()
{
 
}
 
void info::operator <<(int i)
{
    for (string::iterator p = message.begin() ; p != message.end() ; p++) {
        *p = *p - i;
    }
}
 
void info::operator >>(int i)
{
    for (string::iterator p = message.begin() ; p != message.end() ; p++) {
        *p = *p + i;
    }
}
 
info::info(const info &x)
{
    message = x.message;
}
 
info info::operator =(info x)
{
    message = x.message;
    return *this;
}


infoD

Кликните здесь для просмотра всего текста
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
// infoD
string infoD::get_type()
{
    return "infoD";
}
 
void infoD::set(string _message, string _nick)
{
    nick = _nick;
    set_message(_message);
}
 
void infoD::set_m(string _message)
{
 
}
 
infoD::infoD() : info()
{
    nick = "";
}
 
infoD::infoD(string _message, string _nick) : info(_message)
{
    nick = _nick;
}
 
infoD::~infoD()
{
 
}
 
void infoD::set_name(string _message, string _nick)
{
    nick = _nick;
    set_message(_message);
}
 
string infoD::get_message()
{
    return string("Message: ") + message + string(" Name: ") + nick;
}
 
 
string infoD::get_info()
{
    return " " + message + " " + nick;
}
 
bool infoD::operator >(infoD x)
{
    if ((message > x.message)&&(nick > x.nick)) return 1;
    else return 0;
}
 
bool infoD::operator <(infoD x)
{
    if ((message < x.message)&&(nick < x.nick)) return 1;
    else return 0;
}
 
bool infoD::operator ==(infoD x)
{
    if ((message == x.message)&&(nick == x.nick)) return 1;
    else return 0;
}
 
infoD::infoD(const infoD &x)
{
    message = x.message;
    nick = x.nick;
}
 
 
infoD infoD::operator =(infoD x)
{
    message = x.message;
    nick = x.nick;
    return *this;
}
 
ostream &operator<<(ostream &stream, info *x)
{
    stream << " " << x->get_type() << " " << x->get_info();
    return stream;
}
 
 
istream &operator>>(istream &stream, info *x)
{
    string
            _data,
            name;
 
            if(x->get_type() == "info")
            {
                stream >> _data;
                x->set_m(_data);
                return stream;
            }
            if(x->get_type() == "infoD")
            {
                stream >> _data;
                stream >> name;
                x->set(_data,name);
                return stream;
            }
}
 
string infoD::get_n()
{
    return nick;
}
 
void infoD::operator <<(int i)
{
    for (string::iterator p = message.begin() ; p != message.end() ; p++) {
        *p = *p - i;
    }
    for (string::iterator p = nick.begin() ; p != nick.end() ; p++) {
        *p = *p - i;
    }
}
 
void infoD::operator >>(int i)
{
    for (string::iterator p = message.begin() ; p != message.end() ; p++) {
        *p = *p + i;
    }
    for (string::iterator p = nick.begin() ; p != nick.end() ; p++) {
        *p = *p + i;
    }
}
Gr1f0nn
82 / 81 / 42
Регистрация: 30.09.2012
Сообщений: 408
18.11.2014, 20:11  [ТС]     Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined #9
dialog.cpp
Кликните здесь для просмотра всего текста
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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
#include "dialog.h"
#include "ui_dialog.h"
#include "info.h"
#include <QMessageBox>
#include "box.h"
#include <fstream>
 
 
static Box<info*> ob;
Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    ui->deleteCurr->hide();
    ui->name->hide();
    ui->nameLine->hide();
}
 
Dialog::~Dialog()
{
    delete ui;
}
 
void Dialog::on_addLast_clicked()
{
    string data, name;
    info *p;
    if(ui->type->currentText() == "Message")
    {
        if(ui->messageLine->text() != "")
        {
            data = ui->messageLine->text().toStdString();
            p = new info(data);
            //ob += p;
            //ob = ob + p;
            ob.push_back(p);
            QMessageBox::information(this,"Information","Element added!",QMessageBox::Ok);
            ui->messageLine->setText("");
            ui->deleteCurr->show();
            on_show_clicked();
        }
        else QMessageBox::warning(this,"Warning","Please, enter your message!",QMessageBox::Ok);
    }
    if(ui->type->currentText() == "Message + name")
    {
        if(ui->messageLine->text() != "" && ui->nameLine->text() != "")
        {
            data = ui->messageLine->text().toStdString();
            name = ui->nameLine->text().toStdString();
            p = new infoD(data,name);
            //ob += p;
            ob.push_back(p);
            QMessageBox::information(this,"Information","Element added!",QMessageBox::Ok);
            ui->messageLine->setText("");
            ui->nameLine->setText("");
            ui->deleteCurr->show();
            on_show_clicked();
        }
        else QMessageBox::warning(this,"Warning","Please, enter your message!",QMessageBox::Ok);
    }
}
 
void Dialog::on_addBegin_clicked()
{
    string data, name;
    info *p;
    if(ui->type->currentText() == "Message")
    {
        if(ui->messageLine->text() != "")
        {
            data = ui->messageLine->text().toStdString();
            p = new info(data);
           // ob.push_front(p);
            ob.push_front(p);
            QMessageBox::information(this,"Information","Element added!",QMessageBox::Ok);
            ui->messageLine->setText("");
            ui->deleteCurr->show();
            on_show_clicked();
        }
        else QMessageBox::warning(this,"Warning","Please, enter your message!",QMessageBox::Ok);
    }
    if(ui->type->currentText() == "Message + name")
    {
        if(ui->messageLine->text() != "" && ui->nameLine->text() != "")
        {
            data = ui->messageLine->text().toStdString();
            name = ui->nameLine->text().toStdString();
            p = new infoD(data,name);
            ob.push_front(p);
            QMessageBox::information(this,"Information","Element added!",QMessageBox::Ok);
            ui->messageLine->setText("");
            ui->nameLine->setText("");
            ui->deleteCurr->show();
            on_show_clicked();
        }
        else QMessageBox::warning(this,"Warning","Please, enter your message!",QMessageBox::Ok);
    }
}
 
 
 
void Dialog::on_deleteAll_clicked()
{
    if(!ob.empty())
    {
        ob.clear();
        QMessageBox::information(this,"Information","All elements deleted!",QMessageBox::Ok);
        ui->deleteCurr->hide();
        on_show_clicked();
    }
    else
        QMessageBox::warning(this,"Information","List empty!",QMessageBox::Ok);
}
 
void Dialog::on_show_clicked()
{
    if(ob.empty())
    {
        ui->console->clear();
        QMessageBox::warning(this,"Information","List empty!",QMessageBox::Ok);
    }
    else
    {
        ui->console->clear();
        info *el = ob.begin();
        do
        {
            QString msg = QString::fromStdString(el->get_message());
            ui->console->addItem(msg);
            el = el->next;
        }
        while(el != NULL);
    }
}
 
void Dialog::on_deleteLast_clicked()
{
    if(!ob.empty())
    {
       // ob.pop_back();
        --ob;
        QMessageBox::information(this,"Information","Element deleted!",QMessageBox::Ok);
        on_show_clicked();
    }
    else QMessageBox::warning(this,"Information","List empty",QMessageBox::Ok);
    if(ob.empty()) ui->deleteCurr->hide();
}
 
void Dialog::on_deleteFirst_clicked()
{
    if(!ob.empty())
    {
        ob.pop_front();
        QMessageBox::information(this,"Information","Element deleted!",QMessageBox::Ok);
        on_show_clicked();
    }
    else QMessageBox::warning(this,"Information","List empty",QMessageBox::Ok);
    if(ob.empty()) ui->deleteCurr->hide();
}
 
void Dialog::on_deleteCurr_clicked()
{
    QListWidgetItem *current = ui->console->currentItem();
    if(current)
    {
        QString temp = current->text();
        info *el = ob.begin();
        while(QString::fromStdString(el->get_message()) != temp)
        {
            el = el->next;
        }
        if(QString::fromStdString(el->get_message()) == temp)
        {
            ob.erase(el);
            QMessageBox::information(this,"Information","Element deleted!",QMessageBox::Ok);
            on_show_clicked();
        }
        if(ob.empty()) ui->deleteCurr->hide();
    }
}
 
void Dialog::on_type_activated(const QString &arg1)
{
    if(arg1 == "Message")
    {
        ui->name->hide();
        ui->nameLine->hide();
    }
    if(arg1 == "Message + name")
    {
        ui->name->show();
        ui->nameLine->show();
    }
}
 
void Dialog::on_save_clicked()
{
    if(!ob.empty())
    {
        ob.save();
        QMessageBox::information(this,"Information","Saved!",QMessageBox::Ok);
    }
    else QMessageBox::warning(this,"Warning","List empty!",QMessageBox::Ok);
}
 
void Dialog::on_read_clicked()
{
    ifstream fin("data");
    if(fin)
    {
        fin.close();
        //ob.read();
        QMessageBox::information(this,"Information","Readed!",QMessageBox::Ok);
        ui->deleteCurr->show();
        on_show_clicked();
    }
    else QMessageBox::warning(this,"Warning","Error!",QMessageBox::Ok);
}
 
void Dialog::on_edit_clicked()
{
    QListWidgetItem *current = ui->console->currentItem();
    if(current)
    {
        QString temp = current->text();
        info* el = ob.begin();
        while(QString::fromStdString(el->get_message()) != temp)
        {
            el = el->next;
        }
        if(QString::fromStdString(el->get_message()) == temp)
        {
            if(el->get_type() == "info")
            {
                if(ui->messageLine->text() != "")
                {
                    el->set_m(ui->messageLine->text().toStdString());
                    QMessageBox::information(this,"Information","Element edited!",QMessageBox::Ok);
                }
                else QMessageBox::warning(this,"Warning","Please, enter your message!",QMessageBox::Ok);
            }
            else
            {
                if(ui->messageLine->text() != "" && ui->nameLine->text() != "")
                {
                    el->set(ui->messageLine->text().toStdString(), ui->nameLine->text().toStdString());
                    QMessageBox::information(this,"Information","Element edited!",QMessageBox::Ok);
                }
                else QMessageBox::warning(this,"Warning","Please, enter your message!",QMessageBox::Ok);
            }
            on_show_clicked();
        }
    }
}


dialog.h
Кликните здесь для просмотра всего текста
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
#ifndef DIALOG_H
#define DIALOG_H
 
#include <QDialog>
#include "info.h"
 
namespace Ui {
class Dialog;
}
 
class Dialog : public QDialog
{
    Q_OBJECT
    
public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();
    
private slots:
    void on_addLast_clicked();
 
    void on_addBegin_clicked();
 
    void on_deleteAll_clicked();
 
    void on_show_clicked();
 
    void on_deleteLast_clicked();
 
    void on_deleteFirst_clicked();
 
    void on_deleteCurr_clicked();
 
    void on_type_activated(const QString &arg1);
 
    void on_save_clicked();
 
    void on_read_clicked();
 
    void on_edit_clicked();
 
private:
    Ui::Dialog *ui;
};
 
#endif // DIALOG_H


Добавлено через 5 минут
Насчет проблем в проектировке, то у меня с самого начала были сомнения на этот счет. В первую очередь это указатели
C++
1
info *next, *prev;
В классе info. Если я использую стандартный шаблон list, то мне эти указатели не требуются. Следовательно, я как-то могу обойтись без них и здесь. Единственное, что приходит в голову, это создать структуру , в которой будут поля
C++
1
2
3
4
struct elem{
info *next, *prev;
info data;
}
Или что-то подобное. И эту структуру использовать в шаблонном классе. Таким образом, я смогу избавиться от , на мой взгляд, лишних указателей в классе info.

Добавлено через 4 часа 20 минут
Если точнее, то надо, скорее всего, структуру тоже сделать шаблоном:

C++
1
2
3
4
5
6
7
8
template <typename T> struct data
{
    T
        *next;
        *prev;
    T
        data_;
};
update:
Теперь программа ругается как раз на эти указатели из класса info
C++
1
info *next, *prev;
ошибка: request for member 'prev' in '*((Box<info*>*)this)->Box<info*>::tail', which is of non-class type 'info*'
Оно, в принципе, и понятно, ведь шаблон не имеет доступа к этим указателям (или тут дело в другом?)

Структура будет решением этой проблемы или есть решение еще лучше?
Gr1f0nn
82 / 81 / 42
Регистрация: 30.09.2012
Сообщений: 408
18.11.2014, 22:36  [ТС]     Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined #10
В итоге, после некоторых мучений, я все-таки запустил программу и она даже почти корректно работает ^_^
Основные шаблонные функции(добавить в начало\конец, удалить начало\конец\все и т.п.) работают.
Вот измененный шаблон:
Кликните здесь для просмотра всего текста
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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
#ifndef BOX_H
#define BOX_H
#include "info.h"
#include <iostream>
#include <cstring>
#include <string>
#include <fstream>
using namespace std;
 
template <typename X> struct infr
{
    infr<X>
            *next,
            *prev;
    X
            data_;
};
 
template <typename X> class Box
{
private:
    infr<X> *head, *tail;
    int size_;
public:
    Box()
    {
        head = NULL;
        tail = NULL;
        size_ = 0;
    }
 
    ~Box()
    {
        clear();
    }
 
   Box(const Box &x)
    {
        infr<X>
                *temp,
                *curr;
        string
                msg,
                nick;
        head = tail = NULL;
        size_ = 0;
        curr = x.head;
        do {
            if(curr->get_type() == "info") {
                msg = curr->get_m();
                temp = new typename X::base(msg);
            } else {
                msg = curr->get_m();
                nick = curr->get_n();
                temp = new X(msg,nick);
            }
            push_back(temp);
            curr = curr->next;
        } while (curr != NULL);
    }
 
    void push_back(infr<X> *x)
    {
        infr<X>
                *temp;
        temp = x;
        if (!head) {
            tail = head = temp;
            tail->next = NULL;
            tail->prev = NULL;
            size_ ++;
        } else {
            tail->next = temp;
            temp->prev = tail;
            tail = temp;
            tail->next = NULL;
            size_ ++;
        }
    }
 
    void push_front(infr<X> *x)
    {
        infr<X>
                *temp;
        temp = x;
        if (!head) {
            tail = head = temp;
            tail->next = NULL;
            tail->prev = NULL;
            size_ ++;
        } else {
            temp->next = head;
            head->prev = temp;
            head = temp;
            size_ ++;
        }
    }
 
    void pop_back()
    {
       infr<X>
                *temp;
        if (head) {
            temp = tail;
            tail = temp->prev;
            tail->next = NULL;
            delete temp;
            size_ --;
        }
    }
 
    void pop_front()
    {
        infr<X>
                *temp;
        if (head) {
            temp = head;
            head = temp->next;
            head->prev = NULL;
            delete temp;
            size_ --;
        }
    }
 
    void erase(infr<X> *p)
    {
        infr<X>
                *temp;
        temp = p;
        if (temp == begin()) {
            pop_front();
        } else {
            if (temp == end()) {
                pop_back();
            } else {
                if (temp != begin() && temp != end()) {
                    temp->prev->next = temp->next;
                    temp->next->prev = temp->prev;
                    delete temp;
                    size_--;
                }
        }
    }
    }
 
    int size() const
    {
        return size_;
    }
    infr<X> *begin() const
    {
        return head;
    }
    infr<X> *end() const
    {
        return tail;
    }
    void read()
    {
        string
                type;
        X
                *temp;
        infr<X>
                *pole;
        ifstream fin("data");
        if(fin)
        {
            do
            {
                fin >> type;
                if (type == "info") {
                    temp = new  X();
                } else {
                    temp = new typename X::derived();
                }
                fin >> temp;
                pole = new infr<X>;
                pole->data_ = temp;
                push_back(pole);
            }
            while(!fin.eof());
        }
        fin.close();
    }
 
    void save()
    {
       infr<X>
                *temp;
        ofstream
                fout("data");
        if (head) {
            temp = head;
            do {
                fout << temp;
                temp = temp->next;
            } while (temp != NULL);
        }
        fout.close();
    }
 
    bool empty()
    {
        if (head) {
            return 0;
        } else {
            return 1;
        }
    }
 
    void clear()
    {
        infr<X>
                *temp;
        while(head != NULL)
        {
            temp = head;
            head = head->next;;
            delete temp;
        }
        head = tail = NULL;
        size_ = 0;
    }
 
    infr<X> *operator[] (int i)
    {
        infr<X>
                *temp;
        int
                j;
        if (!empty())
            if (i >= 1 && i <= size()) {
                temp = head;
                for( j=0 ; j<i ; j++ ) {
                    temp = temp->next;
                }
                return temp;
            }
        return NULL;
    }
 
    infr<X> *operator() (int i)
    {
        return ((*this)[i]);
    }
 
    Box &operator=(const Box &x)
    {
        infr<X>
                *temp,
                *curr;
        string
                msg,
                nick;
        if(this != &x)
        {
            curr = x.head;
            clear();
            do {
                if(curr->get_type() == "info") {
                    msg = curr->get_m();
                    temp = new typename X::base(msg);
                } else {
                    msg = curr->get_m();
                    nick = curr->get_n();
                    temp = new X(msg,nick);
                }
                push_back(temp);
                curr = curr->next;
            } while (curr != NULL);
        }
        return *this;
    }
 
    friend Box operator+(const Box b,  infr<X> i)
    {
        Box<X> temp;
        temp = b;
        infr<X> *p;
        p = i;
        temp.push_back(p);
        return temp;
    }
 
    friend Box operator+( infr<X> i, const Box b)
    {
        return (b + i);
    }
 
    friend Box operator -(Box b, int i)
    {
        Box<X> temp;
        temp = b;
        infr<X> *p;
        p = temp.begin();
        int j;
        if (i>=1 && i<=temp.size() ) {
            if (i == 1) {
 
                temp.pop_front();
            } else {
                for(j=0 ; j<i ; j++)
                {
                    p = p->next;
                }
                temp.erase(p);
            }
        }
        return temp;
    }
 
    friend Box operator -(int i, Box b)
    {
        return (b - i);
    }
 
    Box operator+=(infr<X> *i)
    {
        push_back(i);
        return *this;
    }
 
    Box operator-=(int i)
    {
        infr<X> *p;
        p = begin();
        int j;
        if (i>=1 && i<=size() ) {
            if (i == 1) {
 
                pop_front();
            } else {
                for(j=0 ; j<i ; j++)
                {
                    p = p->next;
                }
                erase(p);
            }
        }
        return *this;
    }
 
    Box &operator--()
    {
        pop_back();
        return *this;
    }
 
    Box operator--(int notused)
    {
        Box<X> temp = *this;
        --(*this);
        return temp;
    }
};
#endif // BOX_H


Не работает на данный момент функция read

Кликните здесь для просмотра всего текста
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
void read()
    {
        string
                type;
        X
                *temp;
        infr<X>
                *pole;
        ifstream fin("data");
        if(fin)
        {
            do
            {
                fin >> type;
                if (type == "info") {
                    temp = new  X();
                } else {
                    temp = new typename X::derived(); // ругается на эту строчку
                }
                fin >> temp;
                pole = new infr<X>;
                pole->data_ = temp;
                push_back(pole);
            }
            while(!fin.eof());
        }
        fin.close();
    }

Сделал, как Вы посоветовали, то есть написал
C++
1
typedef infoD derived;
Только уже в базовом классе.
Выдает такую ошибку:
Код
ошибка: 'info*' is not a class, struct, or union type
Также еще выдает ошибку насчет того, что нет оператора ввода
Код
ошибка: no match for 'operator>>' in 'fin >> temp'
Данный оператор перегружен в классах info и infoD. Как я понял, компилятор хочет, чтобы функция была шаблонной?
DrOffset
6416 / 3790 / 876
Регистрация: 30.01.2014
Сообщений: 6,575
19.11.2014, 00:05     Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined #11
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
Только уже в базовом классе.
Ну советовал-то я не так А совсем наоборот. Это, по крайней мере, не ломало логику.

Выносить информацию о наследнике в базовый класс - это практически всегда лишает программу логики. Зачем в таком случае вообще это разделение на наследника и базовый класс, если мы рушим инкапсуляцию, наделяя базовый класс знанием о наследнике? Легче в таком случае все реализовать в одном классе и не мучится.
К тому же ты опять начал передавать параметром шаблона тип указателя (я выше задавал наводящий вопрос об этом), соответственно после подстановки у тебя появился
C++
1
X **temp;
Это также повлекло за собой и вторую ошибку с оператором ввода, т.к. он тебя принимает одинарный указатель.
Инстанцировать шаблон надо типом info, а не info*.
Gr1f0nn
82 / 81 / 42
Регистрация: 30.09.2012
Сообщений: 408
19.11.2014, 08:39  [ТС]     Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined #12
DrOffset, да, поздно я понял, что ерунду написал ^_^
Насчет того, что я передаю в параметр шаблона тип указателя, а не сам тип, то вот чем я руководствовался:
Если бы я хранил в контейнере только один тип данных, то я бы передавал info , а не info*, а так как я храню несколько типов данных, то я никак не могу хранить сами объекты, я могу хранить только указатели на них ( или я не прав?)
Собственно, опирался на опыт решения подобной задачи, но с использованием стандартных контейнеров ( в данном случае list) , где я также передавал не сам тип, а казатель на тип данных.
Или это у меня ошибка в понимании того, что именно я должен хранить?

Попробую сделать с info ( может пока буду делать, разберусь как раз ^_^)
DrOffset
6416 / 3790 / 876
Регистрация: 30.01.2014
Сообщений: 6,575
19.11.2014, 14:41     Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined #13
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
Если бы я хранил в контейнере только один тип данных, то я бы передавал info , а не info*, а так как я храню несколько типов данных, то я никак не могу хранить сами объекты, я могу хранить только указатели на них ( или я не прав?)
Не понимаю, честно говоря, твоих затруднений. Безотносительно даже текущего твоего кода:
C++
1
2
3
4
5
6
7
8
9
template <typename X>
class B
{
private:
    X * ptr;  // <-- Добавляем к X звездочку, получаем указатель
};
.....
// Шаблон инстанцируем как
B<SomeClass> p;
В чем проблема так делать?
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
Собственно, опирался на опыт решения подобной задачи, но с использованием стандартных контейнеров ( в данном случае list) , где я также передавал не сам тип, а казатель на тип данных.
Посмотри на стандартный std::list, там передается именно тип элемента.
C++
1
std::list<SomeClass> lst; // элементами list будут объекты SomeClass
Если ты напишешь так:
C++
1
std::list<SomeClass*> lst; // элементами будут указатели на SomeClass
то элементом будет уже указатель, а не значение объекта типа SomeClass.
У тебя же, похоже, требовалась всегда именно последняя запись, потому что на нее была завязана работа твоего списка?
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
Или это у меня ошибка в понимании того, что именно я должен хранить?
Похоже на то.

Добавлено через 3 минуты
Gr1f0nn, Если ты передаешь параметром указатель, то X = YourType *, к такому X не могут быть применены операторы разрешения области видимости ::. И код ломается. Чтобы это работало нужно передавать классовый тип. Об этом тебе и сообщил компилятор:
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
ошибка: 'info*' is not a class, struct, or union type
Gr1f0nn
82 / 81 / 42
Регистрация: 30.09.2012
Сообщений: 408
19.11.2014, 17:37  [ТС]     Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined #14
DrOffset, Спасибо большое! Теперь все стало понятнее

Цитата Сообщение от DrOffset Посмотреть сообщение
У тебя же, похоже, требовалась всегда именно последняя запись, потому что на нее была завязана работа твоего списка?
Я делал так:
C++
1
2
3
4
5
6
7
8
9
list<info*> ob;
info *p;
//some code
p = new info(...);
ob.push_back(p);
//some code
p = new infoD(...);
ob.push_back(p);
// ...
Если же писал
C++
1
list<info> ob;
То не работало ^_^
Как раз тут на форуме вычитал, что хранение указателей на объекты - один из способов хранения объектов разных типов.

Сейчас сделал так:
C++
1
2
3
4
5
6
7
8
9
10
static Box<info> ob;
// ....
string data, name;
    info *u;
//...
u = new info(data);
ob.push_back(u);
// ...
u = new infoD(data,name);
ob.push_back(u);

Теперь буду думать, как реализовать чтение из файла\ конструктор копирования\ присваивания по-другому, так как не получается просто выделить память и под базовый класс, и под наследника в самом шаблоне.
Может здесь может помочь какое-то явное преобразование типов? Хотя везде пишут, что это нежелательно делать, но все-таки вдруг ^_^
DrOffset
6416 / 3790 / 876
Регистрация: 30.01.2014
Сообщений: 6,575
19.11.2014, 18:15     Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined #15
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
Как раз тут на форуме вычитал, что хранение указателей на объекты - один из способов хранения объектов разных типов.
Это так. Только разница в том, что твой класс требует выделения памяти от пользователя всегда. Указатель можно и внутри хранить, необязательно протаскивать его через весь интерфейс. Суть классов и вообще инкапсуляции в том, чтобы более сложные действия и состояния спрятать за более простым интерфейсом. Если делать класс только чтобы был, то эффекта не будет нужного

Цитата Сообщение от Gr1f0nn Посмотреть сообщение
так как не получается просто выделить память и под базовый класс, и под наследника в самом шаблоне.
Ну как же не получается, если я выше дал тебе вполне рабочее решение (в рамках твоей текущей архитектуры)?
Другие дело, что сама архитектура не очень. Но тогда нужно просто с самого начала все продумать заново. Разделить ответственности. Определить сущности их методы их взаимодействия. А потом уже код писать

Цитата Сообщение от Gr1f0nn Посмотреть сообщение
Может здесь может помочь какое-то явное преобразование типов?
Не очень ясно что ты собрался преобразовывать

Добавлено через 7 минут
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
Если же писал
C++
1
list<info> ob;
То не работало ^_^
Не работало потому что так был сделан интерфейс шаблона. Нужно же всегда очень четко понимать что ты делаешь и к чему это приводит. Вслепую тыкаться и менять код наугад - плохая практика.

Цитата Сообщение от Gr1f0nn Посмотреть сообщение
Сейчас сделал так:
На самом деле так даже лучше. В твоей задаче, лучше разделить ответственности. Т.е. есть класс который обобщенно (через указатели на базу) хранит указатели на экземпляры твоих объектов. А есть класс, который управляет, сохранением и восстановлением информации в\из файла.

Добавлено через 18 минут
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
Необходимо создать класс-контейнер, в котором будет храниться пользовательский базовый-класс и класс-наследник. Класс-контейнер реализовать с помощью шаблона.
Вот задача.
Давай ее разберем.
1. Необходимо создать класс-контейнер с помощью шаблона.
2. В нем будут храниться пользовательский базовый-класс и класс-наследник.
Сначала тебе нужно создать класс-шаблон, который будет реализовывать некий контейнер. Ну пусть это будет список. Шаблон намекает на то, что тип данных, хранимый в списке, может быть произвольно заданным.
Потом, используя созданный класс, необходимо поместить в него экземпляры базового класса и экземпляры наследника. Проще всего, как ты правильно заметил, это реализовать используя полиморфизм и указатели.
Теперь нужно создать некую сущность, которая объединит две предыдущие для решения задачи. Например, сохранение и восстановление информации из файла и занесение ее в наш контейнер.

Итого:
У нас есть класс-список, который может быть параметризован каким-либо типом.
И есть два класса: базовый и наследник, которые отражают какую-то предметную область.
И есть класс-менеджер, который занимается управлением данных в списке и сохранением и восстановлением в файл.

Реализуя список, можно смотреть на интерфейс std::list для образца.

Добавлено через 4 минуты
По поводу реализации списка.
Вот этот ход мыслей правильный:
Цитата Сообщение от Gr1f0nn Посмотреть сообщение
Если точнее, то надо, скорее всего, структуру тоже сделать шаблоном:
Только в реализации должно быть так:
C++
1
2
3
4
5
6
template <typename T> 
struct node
{
    node *next, *prev;
    T data_;
};
Т.е. T - это у нас данные. Они и есть параметр шаблона, тип данных, которые мы храним.
node - это у нас внутренняя структура для организации списка. Навигация в памяти осуществляется через указатели на другие такие же node. При правильной реализации методы работы с node должны быть скрыты за интерфейсом list.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.11.2014, 19:08     Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined
Еще ссылки по теме:

Incomplete type used in nested type specifier - Итерация по списку аргументов C++
C++ Шаблонный класс
C++ Field `.` has incomplete type boost::weak_ptr

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

Или воспользуйтесь поиском по форуму:
Gr1f0nn
82 / 81 / 42
Регистрация: 30.09.2012
Сообщений: 408
19.11.2014, 19:08  [ТС]     Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined #16
Цитата Сообщение от DrOffset Посмотреть сообщение
Другие дело, что сама архитектура не очень.
Вот. В этом у меня и проблема, которую я, к сожалению, обнаружил только при создании шаблона
Сейчас пробую спроектировать по-другому классы.
Цитата Сообщение от DrOffset Посмотреть сообщение
Не очень ясно что ты собрался преобразовывать
Я подразумевал что-то вроде dynamic_cast, но опять-таки, это будет свидетельствовать о том, что класс плохо спроектирован.
Цитата Сообщение от DrOffset Посмотреть сообщение
У нас есть класс-список, который может быть параметризован каким-либо типом.
И есть два класса: базовый и наследник, которые отражают какую-то предметную область.
И есть класс-менеджер, который занимается управлением данных в списке и сохранением и восстановлением в файл.
Кажется, уловил суть ^_^

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

Буду пытаться все это теперь реализовать ^_^
Yandex
Объявления
19.11.2014, 19:08     Шаблонный класс. Ошибка : aggregate 'Box<info*> ob' has incomplete type and cannot be defined
Ответ Создать тему
Опции темы

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