Unable to link to an included source file.

Started by
1 comment, last by PumpkinPieman 17 years, 6 months ago
I've been having this really weird bug in VC7 where I'm unable to link to my templated classes for this assignment of mine. When I mean unable to link I mean that the source files are included, all of the proper obj files are generated when compiled, and the header files are in the approprate places. But it still get unresolved externals. (PS, don't ask me why I'm doing something this or that way. I'm just following the requirements for the assignment) Linker Errors:

Assignment 2 error LNK2019: unresolved external symbol "public: __thiscall Set<int>::~Set<int>(void)" (??1?$Set@H@@QAE@XZ) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "public: __thiscall Set<class Date>::~Set<class Date>(void)" (??1?$Set@VDate@@@@QAE@XZ) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "public: __thiscall Set<class Person>::~Set<class Person>(void)" (??1?$Set@VPerson@@@@QAE@XZ) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "public: class Date & __thiscall Set<class Date>::element(void)const " (?element@?$Set@VDate@@@@QBEAAVDate@@XZ) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "public: bool __thiscall Set<class Date>::hasMore(void)" (?hasMore@?$Set@VDate@@@@QAE_NXZ) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "public: void __thiscall Set<class Date>::advance(void)" (?advance@?$Set@VDate@@@@QAEXXZ) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "public: void __thiscall Set<class Date>::reset(void)" (?reset@?$Set@VDate@@@@QAEXXZ) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<<class Person>(class std::basic_ostream<char,struct std::char_traits<char> > &,class Set<class Person> const &)" (??$?6VPerson@@@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABV?$Set@VPerson@@@@@Z) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "public: class Set<class Person> & __thiscall Set<class Person>::operator=(class Set<class Person> const &)" (??4?$Set@VPerson@@@@QAEAAV0@ABV0@@Z) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "public: __thiscall Set<class Person>::Set<class Person>(class Set<class Person> const &)" (??0?$Set@VPerson@@@@QAE@ABV0@@Z) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "public: class Person & __thiscall Set<class Person>::element(void)const " (?element@?$Set@VPerson@@@@QBEAAVPerson@@XZ) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "public: bool __thiscall Set<class Person>::hasMore(void)" (?hasMore@?$Set@VPerson@@@@QAE_NXZ) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "public: void __thiscall Set<class Person>::advance(void)" (?advance@?$Set@VPerson@@@@QAEXXZ) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "public: void __thiscall Set<class Person>::reset(void)" (?reset@?$Set@VPerson@@@@QAEXXZ) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<<class Date>(class std::basic_ostream<char,struct std::char_traits<char> > &,class Set<class Date> const &)" (??$?6VDate@@@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABV?$Set@VDate@@@@@Z) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "public: class Set<class Date> & __thiscall Set<class Date>::add(class Date &)" (?add@?$Set@VDate@@@@QAEAAV1@AAVDate@@@Z) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<<int>(class std::basic_ostream<char,struct std::char_traits<char> > &,class Set<int> const &)" (??$?6H@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABV?$Set@H@@@Z) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "public: class Set<int> & __thiscall Set<int>::add(int &)" (?add@?$Set@H@@QAEAAV1@AAH@Z) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "public: class Person & __thiscall Set<class Person>::someElement(void)const " (?someElement@?$Set@VPerson@@@@QBEAAVPerson@@XZ) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "public: class Set<class Person> & __thiscall Set<class Person>::add(class Person &)" (?add@?$Set@VPerson@@@@QAEAAV1@AAVPerson@@@Z) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "public: __thiscall Set<class Date>::Set<class Date>(int)" (??0?$Set@VDate@@@@QAE@H@Z) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "public: __thiscall Set<int>::Set<int>(int)" (??0?$Set@H@@QAE@H@Z) referenced in function _main
Assignment 2 error LNK2019: unresolved external symbol "public: __thiscall Set<class Person>::Set<class Person>(int)" (??0?$Set@VPerson@@@@QAE@H@Z) referenced in function _main
Assignment 2 fatal error LNK1120: 23 unresolved externals

Set.h

#pragma once
#include <assert.h>
#include <iostream>
#include "vector.h"

template <class T>
class Set
{
public:
	Set(int initial_size = 4);					//default constructor, allocates appropriate heap storage
	Set(const Set<T> & s);						//copy constructor
	~Set(void);									//destructor
	Set<T> & operator=(const Set<T> & s);		//assignment operator
	Set<T> & add(T & element);					//store element
	Set<T> & remove(const T & element);			// remove object equal to element if it  exists
	bool includes(const T & element) const;		// answer whether element is in the set
	T & someElement() const;					//answer some (any) element  of the set but don't remove it

	//Iterator Methods
	void reset();
	bool hasMore();
	void advance();
	T & element() const;

	int size() const; //answer the number of elements in the set.
	void printOn(std::ostream & ostr) const; //print the elements of the set

	const Vector<T>& GetElements() const { return elements; };

private:

	Vector<T> elements;  //set uses a vector to store elements (from assignment #1)
	int numberOfElements; //number of elements in the set
	int capacity; //max. no of elements the set can current memory can hold
	int index;
};

template <class T> std::ostream & operator<<(std::ostream & ostr, const Set<T>& s);

Set.cpp

#include ".\Set.h"

template <class T> std::ostream & operator<<(std::ostream & ostr, const Set<T>& s){
     s.printOn(ostr);
     return ostr;
} 

template <class T> Set<T>::Set<T>(int initial_size = 4)
: elements(initial_size)
, index(0)
{
	numberOfElements = 0;
	capacity = elements.size_max();
}

template <class T> Set<T>::Set<T>(const Set<T>& s)
: elements(s.GetElements())
, index(0)
{
	numberOfElements = elements.size();
	capacity = elements.size_max();
}

template <class T> Set<T>::~Set<T>(void)
{
	
}

template <class T> Set<T> & Set<T>::operator=(const Set<T> & s)
{
	elements = s.elements;

	return *this;
}

template <class T> Set<T> & Set<T>::add(T & element)
{
	if(elements.size() == elements.size_max()){
		elements = Vector<T>(elements.size_max()*2, elements);
	}

	elements.pushFront(&element);

	return *this;
}

template <class T> Set<T> & Set<T>::remove(const T & element)
{
	if(!elements.popElement(&element))
		return *this;

	if(elements.size() > 4){
		if(elements.size() < elements.size_max()/2)
			elements = Vector<T>(elements.size_max()/2, elements);

	}

	numberOfElements = elements.size();

	return *this;
}

template <class T> bool Set<T>::includes(const T & element) const
{
	elements.contains(&element);
}

template <class T> T & Set<T>::someElement() const
{
	return *elements.getElement(rand() % elements.size());
}

template <class T> void Set<T>::reset()
{
	index = 0;
}

template <class T> bool Set<T>::hasMore()
{
	return index > 0 && index <= numberOfElements;
}

template <class T> void Set<T>::advance()
{
	index++;
}

template <class T> T & Set<T>::element()const
{
	assert(numberOfElements == 0); // blah, stupid requirements. You shouldn't use references like this.

	if(index >= numberOfElements)
		return *(elements.getElement(numberOfElements-1));

	return *elements.getElement(index);
}

template <class T> int Set<T>::size()const
{
	return numberOfElements;
}

template <class T> void Set<T>::printOn(std::ostream & ostr) const
{
	
}

Vector.h

#pragma once
#include <assert.h>
#include <iostream>

template <class T>
class Vector
{
public:
	Vector(int initial_size = 4);
	Vector(int initial_size, const Vector<T>& v);
	Vector(const Vector<T>& v);
	~Vector(void);

	int size_max() const;
	int size() const;

	T* getElement(int v)const;
	Vector<T>& operator=(const Vector<T>& v);

    bool pushFront(T* obj);
	bool pushBack(T* obj);
	bool popFront();
	bool popBack();
	bool popElement(T* obj);
	bool contains(T* obj);

	void printOn(std::ostream & os) const;

private:
	T** elements;
	int capacity;
	int numberOfElements;
};

template <class T> std::ostream & operator<<(std::ostream & ostr, const Vector<T> & s);


Vector.cpp

#include ".\Vector.h"

template <class T> std::ostream& operator<<(std::ostream & ostr, const Vector<T> & s){
     s.printOn(ostr);
     return ostr;
}

template <class T> Vector<T>::Vector(int initial_size)
: capacity(initial_size)
, numberOfElements(0)
{
	elements = new T*[capacity];
	ZeroMemory(elements, sizeof(T*)*capacity);
}

template <class T> Vector<T>::Vector(int initial_size, const Vector<T>& v)
: capacity(initial_size)
{
	elements = new T*[capacity];
	ZeroMemory(elements, sizeof(T*)*capacity);

	if(capacity < v.size()){
		for(int i = 0; i < capacity; i++)
			elements = v.getElement(i);
		numberOfElements = capacity;
	}else{
		for(int i = 0; i < v.size(); i++)
			elements = v.getElement(i);
		numberOfElements = v.size();
	}
}

template <class T> Vector<T>::Vector(const Vector<T>& v)
{
	*this = v;
}

template <class T> Vector<T>::~Vector(void)
{
	if(elements)
		delete [] elements;
}

template <class T> int Vector<T>::size_max() const
{
	return capacity;
}

template <class T> int Vector<T>::size() const
{
	return numberOfElements;
}

template <class T> T* Vector<T>::getElement (int v)const
{
	assert( v < 0 || v >= capacity);
	return elements[v];
}

template <class T> Vector<T>& Vector<T>::operator= (const Vector<T>& v)
{
	if(elements)
		delete [] elements;

	T** elements = new T*[v.size_max()];
	ZeroMemory(elements, sizeof(T*)*v.size_max());

	for(int i = 0; i < v.size(); i++){
		elements = v.getElement(i);
	}

	numberOfElements = v.size();

	return *this;
}

template <class T> bool Vector<T>::pushFront(T* obj)
{
	if(numberOfElements >= capacity)
		return false;

	if(numberOfElements == 0)
		return true;

	for(int i = numberOfElements; i > 0; i--)
		elements[i-1] = elements;

	elements[0] = obj;

	numberOfElements++;

	return true;
}

template <class T> bool Vector<T>::pushBack(T* obj)
{
	if(size >= capacity)
		return false;

	elements[size] = obj;
	size++;
}

template <class T> bool Vector<T>::popFront()
{
	if(size == 0)
		return false;

	size--;	
	elements[0] = NULL;

	if(size == 0)
		return true;

	for(int i = 0; i < size; i++)
		elements = elements[i+1];
}

template <class T> bool Vector<T>::popBack()
{
	if(size == 0)
		return false;

	size--;
	elements[size] = NULL;
}

template <class T> bool Vector<T>::popElement(T* obj)
{
	for(int i = 0; i < size; i++){
		if(elements == obj){
			size--;
			for(int j = i; j < size; j++)
				elements[j] = elements[j+1];

			elements[size+1] = NULL;
			return true;
		}
	}

	return false;
}

template <class T> bool Vector<T>::contains(T* obj)
{
	for(int i = 0; i < size; i++)
		if(elements == obj)
			return true;

	return false;
}

template <class T> void Vector<T>::printOn(std::ostream & os) const
{
	for(int i = 0; i < size; i++)
		os << *elements;
}

The Vector class also gives me these errors (When the cpp file is added to main, I can get it to link. It doesn't work at runtime but it links *shrugs*) Thanks
Advertisement
templates cannot be split between .h and .cpp files. it must all be in the header file. templates are pre-compiler structures, not link time structures. each time you declare a new template with a different class as <t> you are creating a whole new class.

so... just move the contents of your .cpp file to the header of your set class and all will be well.

-me
Thanks, that really helped. I was surprised that I didn't know that, I guess I'm just too used to using premade structures so I have little use for my own containers.

This topic is closed to new replies.

Advertisement