error LNK2019: unresolved external symbol in multifile project.

Hello!

I'm running into some problems with my program. I've done some research and it seems to me like I'm doing everything by the book, but I must be missing something because I'm still getting some unresolved external symbol errors.

I've been using C/C++ for a little over two years, but this is my first real venture into multifile programs.

Anyway, here's the code in question.

Array.h
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
#ifndef ARRAY_H
#define ARRAY_H
#include <cassert>

template < class T >
class Array
{
public:
	Array(int size = 1, int growBy = 1);
	virtual ~Array();
	T& operator[](int index);
	int GetSize() {return m_numElements;}
	int GetMaxSize() {return m_maxSize;}
	int GetGrowSize() {return m_growSize;}
	void SetGrowSize(int val)
	{
		assert(val >= 0);
		m_growSize = val;
	}
	virtual int push(T val) {return -1;}
	virtual int search() {return -1;}
	void clear() {m_numElements = 0;}
	void pop();
	void remove(int index);
protected:
	bool Expand();

	T *m_array;
	int m_maxSize;
	int m_growSize;
	int m_numElements;

};
#endif 


Array.cpp
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
#include "Array.h"

template<class T>
Array<T>::Array(int size = 1, int growBy = 1): m_array(NULL), m_maxSize(0), m_growSize(0), m_numElements(0)
{
	if(size > 0)
	{
		m_maxSize = size;
		m_array = new T[m_maxSize];
		m_growSize = ((growBy > 0) ? growBy : 0);
	}
}

template<class T>
virtual Array<T>::~Array()
{
	delete[] m_array;
	m_array = NULL;
}

template<class T>
T& Array<T>::operator[](int index)
{
	assert(m_array != NULL && index < m_numElements);
	return m_array[index];
}

template<class T>
void Array<T>::pop()
{
	if(m_numElements > 0)
		m_numElements--;
}

template<class T>
void Array<T>::remove(int index)
{
	assert(m_array != NULL);
	if(index >= m_maxSize)
		return;
	for(int k = index; k < m_maxSize - 1; k++)
		m_array[k] = m_array[k+1];
	pop();
	if(m_numElements >= m_maxSize)
		m_numElements = m_maxSize - 1;
}

template<class T>
bool Array<T>::Expand()
{
	if(m_growSize <= 0)
		return false;
	T *temp = new T[m_maxSize+m_growSize];
	assert(temp != NULL);
	memcpy(temp, m_array, sizeof(T)*m_maxSize);
	delete[] m_array;
	m_array = temp;
	m_maxSize += m_growSize;
	m_growSize = m_growSize << 1;
	return true;
}


Main.cpp
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
#include <iostream>
#include "OrderedArray.h"
#include "UnorderedArray.h"

using namespace std;

int main(int args, char **argc)
{
	cout << "Unordered Array Example" << endl << endl;
	
	UnorderedArray<int> uArray(3);

	cout << "Pushing 43, 33, 23, 84, 99, 94, and 17 in that order." << endl;

	if(uArray.push(43) != -1)
		cout << uArray.GetGrowSize() << endl;
	if(uArray.push(33) != -1)
		cout << uArray.GetGrowSize() << endl;
	if(uArray.push(23) != -1)
		cout << uArray.GetGrowSize() << endl;
	if(uArray.push(84) != -1)
		cout << uArray.GetGrowSize() << endl;
	if(uArray.push(99) != -1)
		cout << uArray.GetGrowSize() << endl;
	if(uArray.push(94) != -1)
		cout << uArray.GetGrowSize() << endl;
	if(uArray.push(17) != -1)
		cout << uArray.GetGrowSize() << endl;

	cout << "Above numbers represent m_growSize after each successful push" << endl;

	cout << "Popping last element" << endl;
	uArray.pop();

	cout << "Removing element 2" << endl;
	uArray.remove(2);

	cout << "Unordered array contents: ";
	for(int i = 0; i < uArray.GetSize(); i++)
		cout << uArray[i] << " ";

	cout << endl;


	cout << "Search for 12 was found at index: ";
	cout << uArray.search(12);
	cout << endl << endl;

	cout << "Search for 84 was found at index: ";
	cout << uArray.search(84);
	cout << endl << endl;

	cout << "Ordered Array Example" << endl << endl;
	OrderedArray<int> oArray(2,1,false);
	cout << "Duplicates not allowed" << endl;

	cout << "Pushing 43, 33, 23, 84, 99, 94, and 17 in that order, 4 times each" << endl;

	if(oArray.push(43) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(33) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(23) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(84) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(99) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(94) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(17) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(43) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(33) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(23) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(84) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(99) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(94) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(17) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(43) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(33) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(23) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(84) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(99) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(94) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(17) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(43) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(33) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(23) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(84) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(99) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(94) != -1)
		cout << oArray.GetGrowSize() << endl;
	if(oArray.push(17) != -1)
		cout << oArray.GetGrowSize() << endl;
	
	cout << "Above numbers represent m_growSize after each successful push" << endl;

	cout << "Popping last element" << endl;
	oArray.pop();

	cout << "Removing element 2" << endl;
	oArray.remove(2);

	cout << "Ordered array contents: ";
	for(int i = 0; i < oArray.GetSize(); i++)
		cout << oArray[i] << " ";

	cout << endl;


	cout << "Search for 12 was found at index: ";
	cout << oArray.search(12);
	cout << endl << endl;

	cout << "Search for 84 was found at index: ";
	cout << oArray.search(84);
	cout << endl << endl;

	return 0;
}


Everything worked fine when the entire class definition was in the header file, but when I started splitting the code between the header and a cpp file, I started getting these errors. There are 2 additional header files for OrderedArray and UnorderedArray and they both #include "Array.h". All my header files have header guards.

What am I doing wrong?

Also, I'm using Visual Studio 2012 as an IDE.
The code for templates is create `on-demand'. in order to do so, the compiler must see the definitions.
That means that you can't separate in a cpp the definitions, put all in the header.


Well, actually that is not true. You could make explicit instantiation in the cpp, but of just some types, so if you need another it will have linker errors too.
Ahh... makes sense. I'll just revert everything to the way it was before. I'm not going to fool around with explicit instantiation for an array class.

Thanks!
Topic archived. No new replies allowed.