0 / 0 / 0
Регистрация: 16.09.2018
Сообщений: 5
1

Ссылка на неразрешенный внешний символ, Ошибка средств компоновщика LNK2019

16.09.2018, 18:54. Показов 3082. Ответов 8

Author24 — интернет-сервис помощи студентам
После параметризации моего класса стали выскакивать ошибки LNK2019 при вызове из main.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
#pragma once
 
#define START 100
#include <iostream>
#include <set>
#include <algorithm>
#include <iterator>
using namespace std;
 
 
template <class T>
class Elements {
 
private:
    //int size = 0;
    //int *myarray;
    
    int Size() {
        return this->size;
    }
 
    void Clear() {
        this->size = 0;
        delete[] myarray;
    }
 
    void Swap(Elements <T> &set1, Elements <T> &set2) { ///////
        Elements <T> set3;
        set3 = set1;
        set1 = set2;
        set2 = set3;
    }
 
public:
 
    int size = 0;
    T *myarray;
 
    Elements <T>() {                             // конструктор класса
        myarray = new T[START];
        cout << "+CONSTRUCTOR+\n";
    }     
 
    Elements<T>(const Elements <T>&obj)  {      // copy constructor   
        size = obj.size;
        myarray = new T[START];
        for (int i = 0; i < size; ++i) {
            myarray[i] = obj.myarray[i];
        }
        cout << "+COPY CONSTRUCTOR+\n";
    }   
 
    explicit Elements<T>(Elements<T>&& other) {          // move constructor 
        //cout << other;
        size = other.size;
        myarray = new T[START];
        for (int i = 0; i < size; ++i) {
            myarray[i] = other.myarray[i];
        }
        other.Clear();
 
        cout << "+MOVE CONSTRUCTOR+";
    }
 
    ~Elements<T>() {                            //  деструктор
        Clear();
        cout << "+DESTRUCTOR+\n";
    }
 
    int operator [](int n) {
        return this->myarray[n];
    }
    Elements<T>& operator= (const Elements <T> &obj) {
        if (&obj == this)
            return *this;
 
        size = obj.size;
 
        for (int i = 0; i < obj.size; ++i) {
            myarray[i] = obj.myarray[i];
        }
        return *this;
    }
    friend ostream& operator<<(ostream &s, const Elements <T> & obj);
    friend istream& operator>> (istream &s, Elements <T> &obj);
    friend bool operator ==(const Elements <T> &set1, const Elements <T> &set2);
    friend bool operator !=(const Elements <T> &set1, const Elements  <T> &set2);
    friend Elements <T> operator + (const Elements <T> &set1, const Elements <T> &set2);
    friend Elements <T> operator +=(Elements <T> &set1, const Elements <T> &set2);
    friend Elements <T>operator * (const Elements <T> &set1, const Elements <T> &set2);
    friend Elements <T>operator *=(Elements <T> &set1, const Elements <T> &set2);
    void Sort(Elements <T> &set)  {
        for (int i = 0; i < set.size - 1; ++i) {
            for (int j = 0; j < set.size - i - 1; ++j) {
                if (set.myarray[j] > set.myarray[j + 1]) {
                    swap(set.myarray[j], set.myarray[j + 1]);
                }
            }
        }
    }
    friend Elements <T> operator / (const Elements <T> &set1, const Elements <T> &set2);
    friend Elements <T> operator /=(Elements <T> &set1, const Elements <T> &set2);
protected:
 
 
};
 
 
 
template <typename T>
ostream& operator<<(ostream &s, const Elements <T> & obj)     // out
{
    s << "   |   Elements: ";
 
    for (int i =0; i < obj.size; ++i) {
        s << obj.myarray[i] << " ";
    }
    s << "  |\n";
    return s;
} 
 
template <typename T>
istream& operator >> (istream &s, Elements <T> &obj)
{
    cout << "the number of elements of your set (to initialize): ";
    s >> obj.size;
 
    T t;
 
    for (int i = 0; i < obj.size; ++i) {
    cout << "element number " << i + 1 << ": ";
        s >> t;
        obj.myarray[i]=t;
    }
    Sort(obj);
    return s;
}
 
 
template <typename T>
bool operator ==(const Elements <T> &set1, const Elements <T> &set2) {
    if (set1.size != set2.size) return false;
    else {
        for (int i = 0; i < set1.size; ++i) {
            if (set1.myarray[0] != set2.myarray[0]) return false;
        }
        return true;
    }
}
 
template <typename T>
bool operator != (const Elements <T> &set1, const Elements <T> &set2) {
    return !(set1 == set2);
}
 
template <typename T>
void ChangeSize(int OldSize, int NewSize, Elements <T> &obj) {
    Elements <T> temp;
    temp.size = NewSize;
    for (int i = 0; i < min(OldSize,NewSize); ++i) {
        temp.myarray[i] = obj.myarray[i];
    }
    obj = temp;
}
 
template <typename T>
Elements<T> operator + (const Elements <T> &set1, const Elements <T> &set2) {
    Elements <T> set3;
    set3.size = set1.size + set2.size;
    ChangeSize(START, set3.size, set3);
    for (int i = 0; i < set1.size; ++i) {
        set3.myarray[i] = set1.myarray[i];
    }
    for (int i = set1.size; i < set3.size; ++i) {
        set3.myarray[i] = set2.myarray[i - set1.size];
    }
    Sort(set3);
    return set3;
}
 
template <typename T>
Elements <T> operator +=(Elements <T> &set1, const Elements <T> &set2) {
    set1 = set1 + set2;
    Sort(set1);
    return set1;
}
 
template <typename T>
int FindEleminArray(const Elements <T> &set, T el, int from) {
    for (int i = from; i < set.size; ++i) {
        if (set.myarray[i] == el) return i;
    }
    return -1;
}
 
template <typename T>
Elements <T> operator *(const Elements <T> &set1, const Elements <T> &set2) {
    Elements <T> set3;
 
    int t = 0, p = 0, m = 0;
 
    for (int t = 0; t < set1.size; ++t) {
        if (FindEleminArray(set2, set1.myarray[t], p) > -1) {
            set3.myarray[m] = set1.myarray[t];
            ++m;
            p = FindEleminArray(set2, set1.myarray[t], p) + 1;
            ++set3.size;
        }
    }
 
    Sort(set3);
    return set3;
}
 
template <typename T>
Elements <T> operator / (const Elements <T> &set1, const Elements  <T> &set2) {
    Elements <T> set3, set4;
 
    set3 = set1 * set2;
 
    // set1 - set3
 
    int p = 0, m=0;  // с какого искать в сет1
    for (int i = 0; i < set1.size; ++i) {
        if (FindEleminArray(set3, set1.myarray[i], p) < 0) {
            set4.myarray[m] = set1.myarray[i];
            ++m;
            ++set4.size;
 
        }
        else {
            p = FindEleminArray(set3, set1.myarray[i], p) + 1; 
            // или // p = FindEleminArray(set3, set1.myarray[i], p) ; 
        }
    }
 
    Sort(set4);
    return set4;
}
 
 
template <typename T>
Elements <T> operator *=(Elements <T> &set1, const Elements <T>  &set2) {
    set1 = set1 * set2;
    Sort(set1);
    return set1;
}
 
template <typename T>
Elements <T> operator /=(Elements  <T> &set1, const Elements <T>  &set2) {
    set1 = set1 / set2;
    Sort(set1);
    return set1;
}
Для плюса выдает такое: LNK2019 ссылка на неразрешенный внешний символ "class Elements<int> __cdecl operator+(class Elements<int> const &,class Elements<int> const &)" (??H@YA?AV?$Elements@H@@ABV0@0@Z)
Для оператора ввода например так: LNK2019 ссылка на неразрешенный внешний символ "class std::basic_istream<char,struct std::char_traits<char> > & __cdecl operator>>(class std::basic_istream<char,struct std::char_traits<char> > &,class Elements<int> &)" (??5@YAAAV?$basic_istream@DU?$char_traits@D@std@@@std@@AAV01@AAV?$Elements@H@@@Z ) в функции _main
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
16.09.2018, 18:54
Ответы с готовыми решениями:

Ошибка компоновщика: ссылка на неразрешенный внешний символ
Ошибка: ссылка на неразрешенный внешний символ: в строчке: int y = SomeClass::Func(x); Почему я не...

Ошибка LNK2019: ссылка на неразрешенный внешний символ
Уже который день не могу разобраться с этой проблемой! У меня есть класс Agent, с данными name,...

Ошибка LNK2019 ссылка на неразрешенный внешний символ
В заголовочном файле объявлен класс class cLogReader { public: cLogReader(int i) { ...

Ошибка LNK2019 ссылка на неразрешенный внешний символ
Переделывала целочисленнный Список в шаблон + добавила итераторы. но выходят эти ошибки,пофиксить...

8
4063 / 3317 / 924
Регистрация: 25.03.2012
Сообщений: 12,483
Записей в блоге: 1
16.09.2018, 18:58 2
Надеюсь, всё это добро не распихано по различным h и cpp файлам?
И что такое "параметризация класса"?
0
309 / 221 / 74
Регистрация: 23.05.2011
Сообщений: 981
16.09.2018, 19:00 3
Лучший ответ Сообщение было отмечено Iskr как решение

Решение

Перепиши внутри класса вот так:
C++
1
2
template<typename M>
    friend ostream& operator<<(ostream &s, const Elements <M> & obj);
Для всех дружественных функций.
1
0 / 0 / 0
Регистрация: 16.09.2018
Сообщений: 5
16.09.2018, 19:01  [ТС] 4
всё это в файле Elements.h, мейн находится в main.cpp, Elements.h туда подключила.
Это я про template). Когда сделала template пошли эти ошибки.
0
309 / 221 / 74
Регистрация: 23.05.2011
Сообщений: 981
16.09.2018, 19:05 5
Iskr, суть в том, что нужно каждую дружественную функцию темплейтом объявлять отдельно. Общеклассовый к ним не относится.

Добавлено через 1 минуту
Iskr, или делать так: friend ostream& operator<<(ostream &s, const Elements & obj);
То есть, убрать <T> из параметров внутри описания класса.
1
0 / 0 / 0
Регистрация: 16.09.2018
Сообщений: 5
16.09.2018, 19:16  [ТС] 6
New man, Спасибо! вроде помогло

Добавлено через 3 минуты
New man, подскажите пожалуйста, почему до template с функцией sort не было никаких проблем, а теперь при ее вызове из перегрузок <<, +, например, вылетает Ошибка C3861 Sort: идентификатор не найден

Добавлено через 1 минуту
New man, поставила перед её определением "template<typename T>"
0
309 / 221 / 74
Регистрация: 23.05.2011
Сообщений: 981
16.09.2018, 19:26 7
Лучший ответ Сообщение было отмечено Iskr как решение

Решение

Iskr, дело в том, что ты её не совсем правильно написала.

Надо сделать либо так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
void Sort()
{
     for (int i = 0; i < size - 1; ++i) {
            for (int j = 0; j < size - i - 1; ++j) {
                if (myarray[j] > myarray[j + 1]) {
                    swap(myarray[j], myarray[j + 1]);
                }
            }
        }
}
 
// Вызывать так
set.Sort(); // Он отсортирован
Либо так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
static void Sort(Elements& set)
{
     for (int i = 0; i < set.size - 1; ++i) {
            for (int j = 0; j < set.size - i - 1; ++j) {
                if (set.myarray[j] > set.myarray[j + 1]) {
                    swap(set.myarray[j], set.myarray[j + 1]);
                }
            }
        }
}
 
Elements<int>::Sort(elements); // Отсортирован elements
1
0 / 0 / 0
Регистрация: 16.09.2018
Сообщений: 5
16.09.2018, 19:31  [ТС] 8
New man, Спасибо! а без template работало, так и должно было быть?
0
309 / 221 / 74
Регистрация: 23.05.2011
Сообщений: 981
16.09.2018, 19:43 9
Iskr, суть в том, что template<...> автоматически применяется ко всем обозначениям класса внутри тела класса.

C++
1
2
3
4
5
6
7
8
9
10
11
12
template<typename T>
class A
{
public:
   A(); // Тут имеется в виду именно создание A<T>
   A returnA(); // Тут имеется ввиду, что возвращаем именно A<T>
   void getA(A a); // Тут имеется ввиду, что принимает именно A<T> 
};
 
template<typename T>
A<T> A<T>::returnA() // Мы уже не внутри класса, надо явно указать, что A<T>
{}
0
16.09.2018, 19:43
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
16.09.2018, 19:43
Помогаю со студенческими работами здесь

Ошибка LNK2019 ссылка на неразрешенный внешний символ
Ошибка LNK2019 ссылка на неразрешенный внешний символ &quot;void __cdecl sumArray(int * *,int *...

Ошибка LNK2019 - ссылка на неразрешенный внешний символ
Доброго времени суток. При запуске выдается следующую ошибку: LNK2019 ссылка на неразрешенный...

Ошибка LNK2019: ссылка на неразрешенный внешний символ
Есть код, который должен складывать элементы классов. Вопрос, как нечистая сила мне мешает...

Ошибка LNK2019 | Ссылка на неразрешенный внешний символ
Всем добрый день! При компиляции возникает ошибка LNK2019, не могу самостоятельно её отыскать....


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru