Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 33, средняя оценка - 4.67
ramarren14
2 / 2 / 0
Регистрация: 14.07.2011
Сообщений: 49
#1

Шаблонный класс List - C++

17.11.2011, 23:21. Просмотров 4909. Ответов 22
Метки нет (Все метки)

Имеется 2 шаблонных класса List и Node. Один объявлен другом другого. По идее должно работать, но у компилятора другое мнение на этот счет:
1>main.obj : error LNK2019: unresolved external symbol "public: void __thiscall List<int>::PrintListForward(void)const " (?PrintListForward@?$List@H@@QBEXXZ) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "public: void __thiscall List<int>::AddBegining(int)" (?AddBegining@?$List@H@@QAEXH@Z) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall List<int>::List<int>(void)" (??0?$List@H@@QAE@XZ) referenced in function _main
1>C:\Users\selver\documents\visual studio 2010\Projects\List_One\Debug\List_One.exe : fatal error LNK1120: 3 unresolved externals

Класс Node:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef NODE_H
#define NODE_H
 
template <class T>
class Node
{
public:
    Node(T,Node<T>*,Node<T>*);
    Node(T);
private:
    Node<T> * next;
    Node<T> * last;
    int key;
    T data;
};
 
#endif NODE_H
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "Node.h"
template <class T>
Node<T>::Node(T data,Node * next,Node * last)
{
    this->data=data;
    this->next=next;
    this->last=last;
}
 
template <class T>
Node<T>::Node(T data)
{
    this->data=data;
}
класс List:
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
#ifndef LIST_H
#define LIST_H
#include "Node.h"
 
template <class T>
class List
{
public:
    friend class Node<T>;
    List();
    void AddNodeEnd(T data);
    void AddBegining(T data);
    void deleteNodeEnd();
    void deleteNodeBegin();
    int find(int) const;
    void PrintListForward() const;
    void PrintListBack() const;
    void numNode() const;
private:
    Node<T> * head;
    Node<T> * temp;
};
 
#endif 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
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
#include "List.h"
#include "Node.h"
#include<iostream>
 
template <class T>
List<T>::List():
head(NULL),
temp(NULL)
{}
 
template <class T>
void List<T>::AddNodeEnd(T data)
{
    Node<T> * nd=new Node<T>(data,NULL,temp);
    temp=nd;
    if (head)
    {
        Node<T>* current=head;
        while(current->next)
            current=current->next;
            current->last=nd;
    }
    else head=nd;
    numNode();
}
 
template <class T>
void List<T>::AddBegining(T data)
{
    Node<T> * nd=new Node<T>(data);
    if(head)
    {
        Node<T> * tmpt=head;
        head=nd;
        nd->next=tmpt;
    }
    else 
    {
        head=nd;
        nd->next=NULL;
    }
    numNode();
}
 
template <class T>
void List<T>::deleteNodeEnd()
{
    if (temp)
    {
        Node<T> * current=temp;
        current=current->last;
        delete current->next;
        current->next=NULL;
    }
    else
    std::cout<<"list is empty";
}
 
template <class T>
void List<T>::deleteNodeBegin()
{
    if (head)
    {
        Node<T> * tmpt;
        tmpt=head;
        tmpt=tmpt->next;
        delete head;
        head=tmpt;
    }
    else
    std::cout<<"list is empty";
}
 
template <class T>
int List<T>::find(int k) const
{
    Node<T>* current;
    current=head;
    while(current)
    {
        if (current->key==k)
            return current->data;
        current=current->next;
    }
}
 
template <class T>
void List<T>::PrintListForward() const
{
    Node<T> * current=head;
    while(current)
    {
        std::cout<<current->data<<" ";
        current=current->next;
    }
}
 
template <class T>
void List<T>::PrintListBack() const
{
    Node<T> * current=temp;
    while(current)
    {
        std::cout<<current->key<<" "<<current->data;
        current->last;
    }
}
 
template <class T>
void List<T>::numNode() const
{
    Node<T> * counter=head;
    int i=0;
    while (counter)
    {
        counter->key=++i;
        counter=counter->next;
    }
}
main:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<iostream>
#include"Node.h"
#include "List.h"
using namespace std;
 
int main()
{
    List<int> n;
    n.AddBegining(12);
    n.AddBegining(45);
    n.AddBegining(10);
    n.AddBegining(70);
    n.AddBegining(0);
    n.AddBegining(55);
    n.PrintListForward();
    return 0;
}
Без шаблонов все работало.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
17.11.2011, 23:21
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Шаблонный класс List (C++):

Шаблонный класс list - C++
Доброго времени суток, пишу шаблонный list, но вот на определённом этапе возникла ошибка: #ifndef LIST_H #define LIST_H ...

Шаблонный класс list, собственная реализация - C++
Привет всем. Я по чуть-чуть пишу шаблонный класс list с добавлением элементов в начало списка. Уже на свой страх и риск реализовал три...

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

Написать шаблонный класс List для работы с одноправленными списками в динамической памяти - C++
Для объектов класса List определить операции проверки списка на пустоту, добавления элемента в начало списка, в конец списка, подсчет...

Класс Matrix: реализовать шаблонный класс для двумерных массивов - C++
Доброго времени суток. У меня вопрос: я создал класс Array со внутренним динамическим массивом и объекты этого типа смог создать и я ими...

Шаблонный класс и класс одномерный массив - C++
Задание: протестировать класс шаблон, с обычными типами данных я понял как делать, а как передать в шаблон свой класс я не понял. ...

22
lemegeton
2925 / 1354 / 135
Регистрация: 29.11.2010
Сообщений: 2,725
17.11.2011, 23:24 #2
Шаблонный класс нельзя разделять на заголовок и модуль. Это так не работает.
0
prazuber
110 / 110 / 3
Регистрация: 29.04.2010
Сообщений: 240
17.11.2011, 23:32 #3
Да, действительно, шаблонные класы надо сразу целиком писать в хедер-файлах. Например, файл Node.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
#ifndef NODE_H
#define NODE_H
 
template <class T>
class Node
{
public:
 
    Node(T data,Node * next,Node * last)
    {
        this->data=data;
        this->next=next;
        this->last=last;
    }
 
    Node(T data)
    {
        this->data=data;
    }
 
private:
    Node *next;
    Node *last;
    int key;
    T data;
};
 
#endif // NODE_H
Аналогично со вторым файлом.
0
Bers
Заблокирован
18.11.2011, 00:46 #4
Разделять можно. Нужно только знать как. Если не знаешь - пиши все в хэдэр.
0
Chelioss
180 / 180 / 4
Регистрация: 08.01.2011
Сообщений: 1,133
18.11.2011, 01:00 #5
Цитата Сообщение от PraZuBeR Посмотреть сообщение
Node(T data,Node * next,Node * last)
{
this->data=data;
this->next=next;
this->last=last;
}
можно отдельно вынести, но только чтобы в одном хэдере.
0
ramarren14
2 / 2 / 0
Регистрация: 14.07.2011
Сообщений: 49
18.11.2011, 13:25  [ТС] #6
Передалал, но по-прежнему не компилируется. Выдает:
1>c:\users\selver\documents\visual studio 2010\projects\list_one\list_one\list.h(120): error C2955: 'Node' : use of class template requires template argument list
1> c:\users\selver\documents\visual studio 2010\projects\list_one\list_one\node.h(8) : see declaration of 'Node'
1> c:\users\selver\documents\visual studio 2010\projects\list_one\list_one\main.cpp(8) : see reference to class template instantiation 'List<T>' being compiled
1> with
1> [
1> T=int
1> ]

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
#ifndef NODE_H
#define NODE_H
 
 
 
template <class T>
class Node
{
public:
    Node(T data,Node* next,Node* last)
{
    this->data=data;
    this->next=next;
    this->last=last;
}
    
Node(T data)
{
    this->data=data;
}
 
private:
    Node * next;
    Node * last;
    int key;
    T data;
};
 
#endif NODE_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
#ifndef LIST_H
#define LIST_H
#include <iostream>
#include "Node.h"
 
 
template <class T>
class List
{
public:
    friend class Node<T>;
    List():
    head(NULL),
    temp(NULL)
    {}
 
    void AddNodeEnd(T data)
    {
        Node * nd=new Node(data,NULL,temp);
    temp=nd;
    if (head)
    {
        Node* current=head;
        while(current->next)
            current=current->next;
            current->last=nd;
    }
    else head=nd;
    numNode();
    }
 
    void AddBegining(T data)
    {
            Node* nd=new Node(data);
    if(head)
    {
        Node* tmpt=head;
        head=nd;
        nd->next=tmpt;
    }
    else 
    {
        head=nd;
        nd->next=NULL;
    }
    numNode();
    }
 
    void deleteNodeEnd()
    {
            if (temp)
    {
        Node* current=temp;
        current=current->last;
        delete current->next;
        current->next=NULL;
    }
    else
    std::cout<<"list is empty";
    }
 
    void deleteNodeBegin()
    {
            if (head)
    {
        Node* tmpt;
        tmpt=head;
        tmpt=tmpt->next;
        delete head;
        head=tmpt;
    }
    else
    std::cout<<"list is empty";
    }
 
    T find(int key) const
    {
            Node* current;
    current=head;
    while(current)
    {
        if (current->key==k)
            return current->data;
        current=current->next;
    }
    }
 
    void PrintListForward() const
    {
        Node* current=head;
    while(current)
    {
        std::cout<<current->data<<" ";
        current=current->next;
    }
    }
 
    void PrintListBack() const
    {
            Node* current=temp;
    while(current)
    {
        std::cout<<current->key<<" "<<current->data;
        current->last;
    }
    }
 
    void numNode() const
    {
            Node* counter=head;
    int i=0;
    while (counter)
    {
        counter->key=++i;
        counter=counter->next;
    }
    }
 
private:
    Node* head;
    Node* temp;
};
 
 
 
#endif LIST_H
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<iostream>
#include"Node.h"
#include "List.h"
using namespace std;
 
int main()
{
    List<int> n;
    n.AddBegining(12);
    n.AddBegining(45);
    n.AddBegining(10);
    n.AddBegining(70);
    n.AddBegining(0);
    n.AddBegining(55);
    n.PrintListForward();
    return 0;
}
Попробывал писать в List:
Node<T>* head, Node<T>* temp и в функциях заменять Node на Node<T>, ошибок еще больше. Вопрос: так как все таки правильно Node * head, или Node<T>* head?
0
Bers
Заблокирован
18.11.2011, 13:31 #7
ramarren14, закинь всю реализацию своего шаблона в тот же файл хэдэр, где идет объявление самого шаблона.

И объявление, и реализация шаблона находятся в одном файле хэдэре.
0
ramarren14
2 / 2 / 0
Регистрация: 14.07.2011
Сообщений: 49
18.11.2011, 13:38  [ТС] #8
Так? Все равно те же ошибки выдает.
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
#ifndef LIST_H
#define LIST_H
#include <iostream>
 
template <class T>
class Node
{
public:
    Node(T data,Node* next,Node* last)
{
    this->data=data;
    this->next=next;
    this->last=last;
}
    
Node(T data)
{
    this->data=data;
}
 
private:
    Node * next;
    Node * last;
    int key;
    T data;
};
 
 
 
template <class T>
class List
{
public:
    friend class Node<T>;
    List():
    head(NULL),
    temp(NULL)
    {}
 
    void AddNodeEnd(T data)
    {
        Node * nd=new Node(data,NULL,temp);
    temp=nd;
    if (head)
    {
        Node* current=head;
        while(current->next)
            current=current->next;
            current->last=nd;
    }
    else head=nd;
    numNode();
    }
 
    void AddBegining(T data)
    {
            Node* nd=new Node(data);
    if(head)
    {
        Node* tmpt=head;
        head=nd;
        nd->next=tmpt;
    }
    else 
    {
        head=nd;
        nd->next=NULL;
    }
    numNode();
    }
 
    void deleteNodeEnd()
    {
            if (temp)
    {
        Node* current=temp;
        current=current->last;
        delete current->next;
        current->next=NULL;
    }
    else
    std::cout<<"list is empty";
    }
 
    void deleteNodeBegin()
    {
            if (head)
    {
        Node* tmpt;
        tmpt=head;
        tmpt=tmpt->next;
        delete head;
        head=tmpt;
    }
    else
    std::cout<<"list is empty";
    }
 
    T find(int key) const
    {
            Node* current;
    current=head;
    while(current)
    {
        if (current->key==k)
            return current->data;
        current=current->next;
    }
    }
 
    void PrintListForward() const
    {
        Node* current=head;
    while(current)
    {
        std::cout<<current->data<<" ";
        current=current->next;
    }
    }
 
    void PrintListBack() const
    {
            Node* current=temp;
    while(current)
    {
        std::cout<<current->key<<" "<<current->data;
        current->last;
    }
    }
 
    void numNode() const
    {
            Node* counter=head;
    int i=0;
    while (counter)
    {
        counter->key=++i;
        counter=counter->next;
    }
    }
 
private:
    Node* head;
    Node* temp;
};
 
 
 
#endif LIST_H
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<iostream>
#include "List.h"
using namespace std;
 
int main()
{
    List<int> n;
    n.AddBegining(12);
    n.AddBegining(45);
    n.AddBegining(10);
    n.AddBegining(70);
    n.AddBegining(0);
    n.AddBegining(55);
    n.PrintListForward();
    return 0;
}
0
Bers
Заблокирован
18.11.2011, 13:46 #9
Да. Примерно так.

Если не знаешь, как разбивать объявление класса шаблона и реализацию на файлы - всегда пиши все в одном файле.

Ладно, с этим разобрались.

Читать твой код по меньшей мере не приятно, потому что ты не соблюдаешь отступы. Нечитабельно.

Что говорит теперь компилятор?

Добавлено через 5 минут
Цитата Сообщение от ramarren14 Посмотреть сообщение
Node * nd=new Node(data,NULL,temp);
Ну вот здесь например.
Node у тебя - это шаблон, который имеет вид: Node<T>

То есть, Node<int> и Node<std::string> это два принципиально разных типа объектов.
Они занимают разную память.

Ты скармливаешь оператору new какой то непонятный Node
Как он без параметра догадается, для какого типа ему выделять память?
Как он догадается, сколько памяти будит весить объект, если он не знает параметра шаблона?

В общем, все подобные ошибки.
0
ramarren14
2 / 2 / 0
Регистрация: 14.07.2011
Сообщений: 49
18.11.2011, 13:48  [ТС] #10
Ну вот я про это и спрашивал. То есть правильно Node<T>* nd=new Node<T>(data,NULL,temp) ?
0
Bers
Заблокирован
18.11.2011, 13:49 #11
Цитата Сообщение от ramarren14 Посмотреть сообщение
Ну вот я про это и спрашивал. То есть правильно Node<T>* nd=new Node<T>(data,NULL,temp) ?
Да. Я просто хочу, что б ты понял саму идею

Тогда у тебя уже не будит возникать вопросов, когда нужно указывать параметр шаблона, а когда не обязательно.
0
ramarren14
2 / 2 / 0
Регистрация: 14.07.2011
Сообщений: 49
18.11.2011, 14:07  [ТС] #12
Исправил и скомплировал, убрав private в Node, так как компилятор показывал:
1>c:\users\selver\documents\visual studio 2010\projects\list_one\list_one\list.h(62): error C2248: 'Node<T>::next' : cannot access private member declared in class 'Node<T>'
Ну и в таком духе.
Поставил public, сразу заработало.
Странно, почему так происходит, я ведь поставил friend class Node<T>??
0
Bers
Заблокирован
18.11.2011, 14:16 #13
внимательно изучи этот код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
template<class T> class Manager; //предварительное объявление
 
template<class T> 
class Test
{
    friend class Manager<T>;
    int a;  
};
 
template<class T> class Manager
{
    Test<T> myData;
public:
    Manager() { myData.a=10; }
};
 
int main()
{
    Manager<int> check;
    return 0;
}

/зы у тебя в коде присутствует архитектурный фейл. То есть, работать то такой код может быть и будит, но... так делать нельзя. Ты пока ещё не понял в чем заключается идея ООП - "разделяй и властвуй". У тебя по стилю ещё ощущается суржик
0
Riderik
28 / 28 / 1
Регистрация: 24.07.2011
Сообщений: 171
24.11.2011, 23:27 #14
Как разделить шаблон на заголовок и модуль:
Создаешь отдельный хедер, пишешь туда прототип своего шаблона. Далее создаешь отдельный cpp, подключаешь туда хедер шаблона, прописываешь #pragma once, пишешь там реализации. Потом в файлах, где используется шаблон, подключай cpp-файл
0
Bers
Заблокирован
24.11.2011, 23:31 #15
Цитата Сообщение от Riderik Посмотреть сообщение
Как разделить шаблон на заголовок и модуль:
Создаешь отдельный хедер, пишешь туда прототип своего шаблона. Далее создаешь отдельный cpp, подключаешь туда хедер шаблона, прописываешь #pragma once, пишешь там реализации. Потом в файлах, где используется шаблон, подключай cpp-файл
И где здесь модульность?
0
24.11.2011, 23:31
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
24.11.2011, 23:31
Привет! Вот еще темы с ответами:

Переделать класс в шаблонный класс - C++
Как данный процесс проделать? Я попробовал так по синтаксису из учебника: #include &lt;iostream&gt; #include &lt;fstream&gt; using...

шаблонный класс - C++
реализован согласно &quot;Создание конструкторов и деструктора&quot; на шаблон класса с параметром -Тип данных в файле, редактируется (байт / слово /...

Шаблонный класс - C++
#include &lt;iostream&gt; using namespace std; template &lt;class T&gt; class Vector{ private: int size, capacity; T* data; public: ...

Шаблонный класс - C++
Подскажите как указать реализацию методов для шаблонного класса template &lt;class T_machine&gt; class hospital_room { ...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

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