Linking Headers - Doubly Linked List

Hi all,

I'm having some trouble about linking my project with the IDE Visual Studio C++ 2008. If anyone could help me I would be thankful.

See code below:

ListNode.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

#ifndef LISTNODE_H
#define LISTNODE_H

template< typename nodeType >
class ListNode
{
public:
	ListNode( int, nodeType );
	int getCode() const;
	nodeType getValue() const;
	void setCode( int );
	void setValue( nodeType );
	ListNode< typename nodeType >* getNextNode() const;
	ListNode< typename nodeType >* getPrevNode() const;
	void setNextNode( ListNode< typename nodeType >* );
	void setPrevNode( ListNode< typename nodeType >* );
private:
	int code;
	nodeType value;
	ListNode< typename nodeType >* nextNode;
	ListNode< typename nodeType >* prevNode;
};

#endif


ListNode.cpp
1
2
3
4
5
6
7
8
9
10

#include <iostream>
using std :: cout;
using std :: cin;
using std :: endl;

#include "ListNode.h"

member function definitions


List.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

#ifndef LIST_H
#define LIST_H

#include "ListNode.h"

template< typename nodeType >
class List
{
public:
	List();
	~List();
	void addNode( int, nodeType );
	void withdrawNode( int );
	void printNode( int ) const;
	void printList() const;
private:
	ListNode< typename nodeType >* firstNode;
	ListNode< typename nodeType >* lastNode;

	//funções utilidade. Será usada somente dentro da classe.
	//Promove maior reusabilidade
	ListNode< typename nodeType >* allocNode( int, nodeType );
	ListNode< typename nodeType >* exists( int ) const;
	bool isLastNode( ListNode< typename nodeType >* );
	bool isFirstNode( ListNode< typename nodeType >* );
};

#endif 


List.cpp
1
2
3
4
5
6
7
8
9

#include <iostream>
using std :: cout;
using std :: cin;
using std :: endl;

#include "List.h"

member functions defenitions


Driver Program
1
2
3
4
5
6
7
8
9

#include< iostream >
using std :: cout;
using std :: cin;
using std :: endl;

#include "List.h"

main function and other test functions


The code works well if I put all the .cpp and the .h files all together, but otherwise i receive the following messages from the Visual C++ 2008 compiler:

------ Build started: Project: (Template) Lista duplamente encadeada, Configuration: Debug Win32 ------
Compiling...
List.cpp
Linking...
Driver.obj : error LNK2019: unresolved external symbol "public: __thiscall List<float>::~List<float>(void)" (??1?$List@M@@QAE@XZ) referenced in function _main
Driver.obj : error LNK2019: unresolved external symbol "public: void __thiscall List<float>::printNode(int)const " (?printNode@?$List@M@@QBEXH@Z) referenced in function _main
Driver.obj : error LNK2019: unresolved external symbol "public: void __thiscall List<float>::printList(void)const " (?printList@?$List@M@@QBEXXZ) referenced in function _main
Driver.obj : error LNK2019: unresolved external symbol "public: void __thiscall List<float>::withdrawNode(int)" (?withdrawNode@?$List@M@@QAEXH@Z) referenced in function _main
Driver.obj : error LNK2019: unresolved external symbol "public: void __thiscall List<float>::addNode(int,float)" (?addNode@?$List@M@@QAEXHM@Z) referenced in function _main
Driver.obj : error LNK2019: unresolved external symbol "public: __thiscall List<float>::List<float>(void)" (??0?$List@M@@QAE@XZ) referenced in function _main
C:\Documents and Settings\Lucas\Desktop\(Template) Lista duplamente encadeada\Debug\(Template) Lista duplamente encadeada.exe : fatal error LNK1120: 6 unresolved externals
Build log was saved at "file://c:\Documents and Settings\Lucas\Desktop\(Template) Lista duplamente encadeada\(Template) Lista duplamente encadeada\Debug\BuildLog.htm"
(Template) Lista duplamente encadeada - 7 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Thanks
This is coming up so much, lately, I might consider writing an article about it.

Template functions have to be declared and defined in the same file.
Like helios mentioned it has to be in the same file. I don't prefer actually putting the source code for my template header and source file in the same file though, and so there is a way to keep them separate. You can use an "inline" file to do this (An inline file ends with the extension inl). The logic is similar, but backwards. You're going to include your implementation file into your header file instead of the other way around. Here's an example of how to do this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//TemplateTest.hpp
#ifndef TEMPLATETEST_HPP
#define TEMPLATETEST_HPP

template <typename T>
class TemplateTest
{
public:
	T getDataMember();
	void setDataMember(T value);
private:
	T dataMember;
};

#include "TemplateTest.inl"

#endif //TEMPLATETEST_HPP 


1
2
3
4
5
6
7
8
9
10
11
12
// TemplateTest.inl
template <typename T>
T TemplateTest<T>::getDataMember()
{
	return dataMember;
}

template <typename T>
void TemplateTest<T>::setDataMember(T value)
{
	dataMember = value;
}


I hope this helps. ^^
Ok. Thank you.
I don't prefer actually putting the source code for my template header and source file in the same file
Why not?
At the moment I'm an amateur programmer (still in school for it) and so this is just preference when working on my own projects. It's easier for me to look at the header and get the overview of the class and have another file have the implementation probably because of habit. I use Visual Studio more than anything else so I like just using two panes to have both open when I'm working on the class.

I'm not saying it's better, and it very well may be worse. I don't really know (Perhaps you could illuminate us?).
Last edited on
It's the same. The preprocessor just pastes everything together, so the result is the same as just putting the definition inside the class.
I do agree that it's easier to look at the function without that extra clutter, but I like even less the idea of yet another file.
If the function was particularly large (which is not advisable, since it's being compiled at least once for every file that includes the header), I'd do what you do, but including the definitions myself:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
template <typename T>
class TemplateTest{
public:
	T getDataMember();
	void setDataMember(T &value);
private:
	T dataMember;
};

template <typename T>
T TemplateTest<T>::getDataMember(){
	return dataMember;
}

template <typename T>
void TemplateTest<T>::setDataMember(T &value){
	dataMember = value;
}
Well, for what I have been reading about software enginnering the professional class implementation programmers have to separate the interface from the implementation by putting them in two separate files. That is because the class implementation programmer "needs" to hide from the user programmer the implementation of the class once the interface is the only thing that the user must acknoledge from the class, not its attributes or private members. Of course that for some of us learners that is not something "must-do", but if anyone intends to follow the programmer carrer it's better to get use to this recomendation.

That's why i wanted to put the headers separated from the members definition.

If I said something wrong, please tell me.


Last edited on
Topic archived. No new replies allowed.