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

C++

Войти
Регистрация
Восстановить пароль
 
insideone
Модератор
Автор FAQ
3638 / 916 / 49
Регистрация: 10.01.2010
Сообщений: 2,469
#1

Компоновщик vs. Шаблоны - C++

17.03.2010, 20:29. Просмотров 638. Ответов 2
Метки нет (Все метки)

Впервые реально понадобились шаблоны и.. затык Компановщик ругается так:
1>------ Построение начато: проект: Scene, Конфигурация: Debug Win32 ------
1>Компоновка...
1>Main.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: __thiscall List<class Object>::~List<class Object>(void)" (??1?$List@VObject@@@@QAE@XZ) в функции _main
1>Main.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: class List<class Object> & __thiscall List<class Object>::operator++(int)" (??E?$List@VObject@@@@QAEAAV0@H@Z) в функции _main
1>Main.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: class List<class Object> & __thiscall Node<class Object>::Childs(void)" (?Childs@?$Node@VObject@@@@QAEAAV?$List@VObject@@@@XZ) в функции _main
1>Main.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: class List<class Object> & __thiscall List<class Object>::operator>>(class Object *)" (??5?$List@VObject@@@@QAEAAV0@PAVObject@@@Z) в функции _main
1>Main.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: class Object * __thiscall List<class Object>::operator->(void)" (??C?$List@VObject@@@@QAEPAVObject@@XZ) в функции _main
etc
Собственно в Main такое дело:
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
#include "windows.h"
#include <iostream>
#include "Object.h"
#include "List.h"
#include "Node.h"
using namespace std;
 
int main(){
    List<Object> a;
    a[-1] << Object(0) << Object(2);
    a[0] << Object(1);
    Node<Object>& ListNode = a[-1];
    a[ListNode] << Object(3);
    for (a[-1]; a == NULL; a--)
    {
        cout << " '" << a->info << "'";
    }
    a[3] >> NULL >> NULL >> NULL;
    cout << endl;
    Node<Object>& a0 = a[0];
    a0.Childs() << Object(3);
    for (a[0]; a == NULL; a++)
    {
        cout << " '" << a->info << "'";
    }
 
return 0;
}
Шаблоны задавались так:
List.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
#ifndef LIST_GUARDED
 
    #define LIST_GUARDED
 
    #define NODS_ALLOCED    1000
 
    #define TEMPLATE template <class data_type>
    #define NODE Node<data_type>
    #define LIST List<data_type>
 
    TEMPLATE class Node;
 
    enum ADAPT_MODE{    BEFORE, AFTER       };
 
    TEMPLATE    class List{
    friend class NODE;
        static NODE* NodesMem;
        static NODE* Nodes;
        static unsigned char ListCount;
 
        void AllocNodes();
        void FreeNodes();
 
        // Вспомогательные функции помогающией переходить
        // узлу база <-> список
        static NODE* Wrest(NODE* Whole);
        static NODE* Adapt(LIST*const _this, NODE* Adaptive, NODE* Friend, ADAPT_MODE Mode);
        void Wash(NODE* Dirty);
 
        // Из базы в список
        NODE* GetNode();
        void SendNode(NODE* Died);
 
        NODE* Parent; // Родоначальный нод
        NODE *Head, *Tail; // Начало и конец списка
 
        NODE* CurrentNode; // для перемещения по списку
        size_t Count; // количество элементов в списке (без учета вложенных списков)
    public:
        // Перемещение по списку
        LIST& operator ++(int);// CurrentNode = CurrentNode->Next;
        LIST& operator --(int);// CurrentNode = CurrentNode->Prev;
        LIST& operator [] (long int Offset); // CurrentNode->[Offset]Next;
        LIST& operator [] (NODE& SetNODE); // CurrentNode = SetNODE;
        operator NODE&(); // return CurrentNode;
        data_type* operator ->(); // return CurrentNode->Data;
        bool operator == (NODE* StopNODE); // return (CurrentNode == StopNODE);
 
 
        // Добавление данных в список после текущего нода
        LIST& operator << (data_type& newData);
        // Удаляет текущий нод из списка
        LIST& operator >> (data_type* saveData);
 
        LIST& Childs(); // return CurrentNode->Childs()
 
        NODE* GetTail();
        NODE* GetHead();
 
        List();
        ~List();
    };
#endif
List.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
#include "windows.h"
#include "Node.h"
#include "List.h"
 
TEMPLATE
NODE* LIST::NodesMem = NULL;
 
TEMPLATE
NODE* LIST::Nodes = NULL;
 
TEMPLATE
unsigned char LIST::ListCount = 0;
 
TEMPLATE
LIST::List(){
    memset(this, 0, sizeof *this);
    ListCount++;
    AllocNodes();
}
 
TEMPLATE
LIST::~List(){
    if ( --ListCount == 0 )
        FreeNodes();
}
 
TEMPLATE
void LIST::AllocNodes(){
    if ( NodesMem != NULL ) return;
    // Выделение нодов
    NodesMem = Nodes = new Node[NODS_ALLOCED];
    Node* StopNode = (NodesMem + NODS_ALLOCED), *CurNode = NodesMem;
    // Пока не прошли все ноды
    while (CurNode != StopNode)
    {
        // Устанавливаем связи
        CurNode->Next = CurNode + 1;
        CurNode->Prev = CurNode - 1;
        CurNode++; // Следующий нод
    }
    NodesMem->Prev = NULL;
    CurNode--; CurNode->Next = NULL;
}
 
TEMPLATE
void LIST::FreeNodes(){
    delete [] NodesMem; NodesMem = NULL;
}
 
TEMPLATE
NODE* LIST::Wrest(NODE* Wrested){
    if ( Wrested->Parent != NULL )
    {
        if ( Wrested->Parent->Tail == Wrested ) // если вырываем нод из хвоста списка
            Wrested->Parent->Tail = Wrested->Parent->Tail->Prev; // делаем новый хвост
        if ( Wrested->Parent->Head == Wrested ) // если вырываем нод из головы списка
            Wrested->Parent->Head = Wrested->Parent->Head->Next; // делаем новую голову
    }
    NODE
        *Prev   = Wrested->Prev,
        *Next   = Wrested->Next;
    if ( Prev   != NULL )   Prev->Next = Next;
    if ( Next   != NULL )   Next->Prev = Prev;
 
    // Делаем полной сиротой
    Wrested->Parent = NULL; Wrested->Child = NULL;
    Wrested->Prev = NULL; Wrested->Next = NULL;
return Wrested;
}
 
TEMPLATE
NODE* LIST::Adapt(LIST*const _this, NODE* Adaptive, NODE* Friend, ADAPT_MODE Mode){
    Wrest(Adaptive); // Отрываем адаптируемый от старого списка
    Adaptive->Parent = _this; // Новый родитель нода - текущий список
 
    if ( _this != NULL )
    {
        if ( Friend == NULL ) Friend = _this->Tail;
        if ( _this->Head == NULL ) _this->Tail = _this->Head = Adaptive;
        if ( Friend == NULL ) return _this->Head;
    }
 
    switch(Mode)
    {
    case BEFORE:
        {
            NODE
                *Before = Friend->Prev,
                *After = Friend;
                                    Adaptive->Next = After;
            if ( After != NULL )    After->Prev = Adaptive;
 
                                    Adaptive->Prev = Before;
            if ( Before != NULL )   Before->Next = Adaptive;
 
            if ( _this != NULL )
                if ( _this->Head == Friend )
                    _this->Head = Adaptive;
            else
                if ( Nodes == Friend )
                    Nodes = Adaptive;
        }
        break;
    case AFTER:
        {
            NODE
                *Before = Friend,
                *After = Friend->Next;
                                    Adaptive->Next = After;
            if ( After != NULL )    After->Prev = Adaptive;
 
                                    Adaptive->Prev = Before;
            if ( Before != NULL )   Before->Next = Adaptive;
 
            if ( _this != NULL && _this->Tail == Friend ) _this->Tail = Adaptive;
        }
        break;
    }
 
return Adaptive;
}
 
TEMPLATE
NODE* LIST::GetNode(){
    NODE* NextNode = Nodes->Next;
    NODE* RetNode = Wrest(Nodes);
    Nodes = NextNode;
return RetNode;
}
 
TEMPLATE
void LIST::SendNode(NODE* Died){
    Wrest(Died); // отрываем от текущего списка
    Adapt(NULL, Died, Nodes, BEFORE); // вставляем в начало списка выделенной памяти нодов
}
 
// Перемещение по списку
TEMPLATE
LIST& LIST::operator ++(int){
    if ( CurrentNode != NULL )
        CurrentNode = CurrentNode->Next;
return *this;
}
 
TEMPLATE
LIST& LIST::operator --(int){
    if ( CurrentNode != NULL )
        CurrentNode = CurrentNode->Prev;
return *this;
}
 
TEMPLATE
LIST::operator NODE&(){
    return *CurrentNode;
}
 
TEMPLATE
LIST& LIST::operator [] (long int Offset){
    if (Offset < 0)
    {
        CurrentNode = Tail; Offset = -Offset - 1;
        while ( CurrentNode != NULL && Offset-- ) CurrentNode = CurrentNode->Prev;
    } else {
        CurrentNode = Head;
        while ( CurrentNode != NULL && Offset-- ) CurrentNode = CurrentNode->Next;
    }
return *this;
}
 
TEMPLATE
LIST& LIST::operator [] (NODE& StartNode){
    if ( StartNode.Parent == this ) // только для своих нодов
        CurrentNode = &StartNode;
    //else
    //  LOG("Выход за пределы списка List", NULL);
return *this;
}
 
TEMPLATE
bool LIST::operator == (NODE* StopNode){
    return (CurrentNode != StopNode);
}
 
TEMPLATE
data_type* LIST::operator ->(){
    //if ( CurrentNode == NULL ) return NULL;
return &CurrentNode->Data();
}
 
 
// Добавление данных в список
TEMPLATE
LIST& LIST::operator << (data_type& newData){
    NODE* NewNode = GetNode(); if ( NewNode == NULL ) return *this; // память кончилась
 
    Count++;
 
    NewNode->Data() = newData;
 
    Adapt(this, NewNode, CurrentNode, AFTER); // вставляем в конец текущего списка
return *this;
}
 
TEMPLATE
LIST& LIST::operator >> (data_type* saveData){
    if ( CurrentNode == NULL ) return *this; // вырывать нечего
 
    Count--;
 
    NODE* NewCurrent = (CurrentNode->Next == NULL)?CurrentNode->Prev:CurrentNode->Next;
 
    SendNode(CurrentNode);
 
    if ( saveData != NULL ) *saveData = *CurrentNode;
    
    CurrentNode = NewCurrent;
return *this;
}
 
TEMPLATE
LIST& LIST::Childs(){
    if ( CurrentNode == NULL ) return (List & )CurrentNode;
return CurrentNode->Childs();
}


Node.cpp и Node.h подобным образом...
Локти уж изгрыз... Где моя ошибка?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
17.03.2010, 20:29     Компоновщик vs. Шаблоны
Посмотрите здесь:

Шаблонный класс от шаблонного класса, ругается компоновщик - C++
абстрактный класс Хэширования template &lt;class typeHashData, class typeHashIndex&gt; class AbstarctHash { private: public: ...

Компоновщик о ликовка программы это одно и тоже? - C++
??????

Как на физическом уровне работает компоновщик в приведенном случае - C++
Всем привет! Уважаемые форумчане объясните мне, как, на физическом уровне, работает компоновщик в этом случае: //файл Class.h ...

Как влияет inline и обертка(#ifndef #define #endif) .h файла на компоновщик. - C++
Есть файл Point.h: #ifndef POINT_GUARD #define POINT_GUARD ...

Возможно ли подгрузить библиотеку так, чтоб компоновщик подгружал функции из основной программы? - C++
Всем привет! Хотелось бы узнать, возможно ли подгрузить библиотеку так, чтоб компоновщик подгружал функции из основной программы? ...

Курсовая работа "Паттерн Компоновщик. Расчет стоимости оборудования исходя из его составных частей." - C++
Предлагаю ознакомиться с моей курсовой работой на данную тему. С заинтересованными обсудим на каких условиях я предоставлю все файлы...

Шаблоны в C++ - C++
Доброго времени суток! Начал разбираться что такое шаблон и с чем его едят. Загуглил, вставил код из википедии. Ошибка. ...

шаблоны - C++
помогите с задачей пожалуйста нужно описать шаблон класса для хранения последовательности пар ключ - значение, написать функцию ...

Шаблоны - C++
template &lt;typename Type&gt; bool Func(Type &amp;data) { } Как сделать, что бы шаблон работал только для некоторых типов? Скажем...

шаблоны в си++ - C++
кто может сказать где прблема? List.h #ifndef LIST_H #define LIST_H #include&lt;iostream&gt; #include&lt;ostream&gt; ...

Шаблоны - C++
Здравствуйте не объясните новичку пару аспектов про шаблоны 1)Зачем они нужны 2)Преимущества 3)Синтаксис 4)Маленький примерчик

шаблоны - C++
Помогите пож. разобраться с шаблонами. Шаблоны у которых параметры тоже шаблоны. из книги: tamplate&lt;typenamy T&gt;class Thing здесь...


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

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Genius Ignat
1235 / 773 / 44
Регистрация: 16.09.2009
Сообщений: 2,014
17.03.2010, 21:11     Компоновщик vs. Шаблоны #2
Шаблоны должны объявляются и реализуются только в заголовочных .h файлах...

Добавлено через 26 минут
Хочешь убедиться в этом посмотри в какой нибудь заголовок библиотеки: STL
insideone
Модератор
Автор FAQ
3638 / 916 / 49
Регистрация: 10.01.2010
Сообщений: 2,469
17.03.2010, 23:08  [ТС]     Компоновщик vs. Шаблоны #3
Спасибо, все решилось. Чтож получается любое изменение реализации заставит все перекомпилироваться, не есть хорошо... жаль через void* нельзя делать, мне нужно тип знать, т.к. конструкторы для добавленных данных вызываются... буду думать
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru