static initialisation in source files, VC++

Started by
16 comments, last by random_thinker 18 years, 7 months ago
When you have static data members in a class, you have to add a declaration in a source file that is compiled, right?

#ifndef _IMBASE_CPP_
#define _IMBASE_CPP_

#include "list.h"
#include "IMBase.h"


util::list<IMBase*> IMBase::activeList;		///< The list of active objects (with ref_count > 0)
util::list<IMBase*> IMBase::deadList;		///< The list of dead objects (with ref_count == 0)


#endif




#ifndef _IMBASE_H_
#define _IMBASE_H_

#include "list.h"

/**
 * Provides the basic menmory managment for objects.
 */
class IMBase
{
private:

	static util::list<IMBase*> activeList;		///< The list of active objects (with ref_count > 0)
	static util::list<IMBase*> deadList;		///< The list of dead objects (with ref_count == 0)

	long ref_count;			///< Reference variable

public:

	// functions
};



So, shouldn't this work? I've added the IMBase source file to the project, and the IMBase header is included where it needs to be. Also the list header file is included and the list source file is added to the project. So, theoretically, shouldn't this be working? I'm still getting:

IMBase.obj : error LNK2001: unresolved external symbol 
"public: __thiscall util::list<class IMBase *>::list<class IMBase *>(void)" (??0?$list@PAVIMBase@@@util@@QAE@XZ)
IMBase.obj : error LNK2001: unresolved external symbol 
"public: __thiscall util::list<class IMBase *>::~list<class IMBase *>(void)" (??1?$list@PAVIMBase@@@util@@QAE@XZ)
Debug/test.exe : fatal error LNK1120: 2 unresolved externals


[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Advertisement
I will have to question your use of those include guards on your .CPP file. Try taking those off and recompiling (clean then rebuild). Right now, other than that, your method of declaring them in the .CPP file looks correct to me.
The include guards in the source file was habit from a time I didn't use project files properly. [smile]

Nah, it didn't work. Anything else that could be the problem?
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Well then it seems that the .cpp file is not being compiled for some reason. Try moving the two statements:
util::list<IMBase*> IMBase::activeList;		///< The list of active objects (with ref_count > 0)util::list<IMBase*> IMBase::deadList;		///< The list of dead objects (with ref_count == 0)


to your Main.cpp file (make sure it includes the IMBase.h) and rebuild to see if that works.

The only other thing I can think of is that if the util::list is your own user defined data type that represents a list (as in you are not using the stl's list class) then it may be a template problem then. But try the first part of this post first, if it fails still, can we see the util class's definition.
Still didn't work.

#ifndef _UTIL_LIST_H_#define _UTIL_LIST_H_#include <stddef.h>namespace util{/** * A templated doubly linked list class */template <class T>class list{private:	/**	 * A node in a doubly linked list.	 */	struct Node{		T obj;			///< An object of type T		Node* next;		///< A pointer to the next node		Node* prev;		///< A pointer to the previous node		/**		 * Constructor		 * \param o A const reference to an object of type T		 * \param n A pointer to the next node in the list		 * \param p A pointer to the previous node in the list		 */		Node(const T& o, Node* n = NULL, Node* p = NULL)			:	obj(o), next(n), prev(p)		{	}	};	Node* head;				///< The first linked list element in the list	unsigned int size;		///< The number of elements in the listpublic:	/**	 * An iterator that is used to step through the linked list	 */	struct iterator{	private:		friend class list<T>;		///< Declare this a friend to list<T> so, list<T> can access its members		Node* current;				///< The current list element being pointed to	public:		/**		 * Constructor		 * \param n A pointer to an element in the list		 */		iterator(Node* n = NULL)			:	current(n)		{	}		/**		 * Overloaded operator*  (for de-referencing)		 * \return A reference of type T to the object element of the		 */		T& operator*()		{	return current->obj;	}		/**		 * Overloaded prefix operator++ (but will be used as postfix default function for iterator)		 * Moves the iterator forward in the list		 */		void operator++(int j)			{				if( current == NULL )				return;			else				current = current->next;		}		/**		 * Overloaded prefix operator-- (but will be used as postfix default function for iterator)		 * Moves the iterator backward in the list		 */		void operator--(int j)		{			if( current == NULL )				return;			else				current = current->prev;		}		/**		 * Overloaded operator==		 * \param i A const reference to an iterator object		 * \return true if current pointer is equal to i.current pointer, else false		 */		bool operator==(const iterator& i)	{	return current == i.current;	}		/**		 * Overloaded operator!=		 * \param i A const reference to an iterator object		 * \return true if current pointer is not equal to i.current pointer, else false		 */		bool operator!=(const iterator& i)	{	return current != i.current;	}		/**		 * Overloaded assignment operator		 * \param i A const refernce to an iterator object		 * \return A reference to 'this' iterator object		 */		iterator& operator=(const iterator& i)		{			if( &i != this )				current = i.current;			return *this;		}	};	// iterator	/**	 * Constructor	 */	list();	/**	 * Copy constructor	 * \param l A const reference to a list object	 */	list(const list& l);	/**	 * Destructor	 */	~list();	/**	 * Delete all elements in the list.	 */	void clear();	/**	 * Return an iterator to the first element in the list	 * \return An iterator object to the first element in the list.	 */	iterator begin() const;	/**	 * Return an iterator to the point after the last element in the list,	 * which effectively is a NULL pointer.	 */	iterator end() const;	/**	 * Add an element to the back of the list.	 * \param o A const reference to an object of type T	 */	void push_back(const T& o);	/**	 * Add a list element to the front of the list	 * \param o A const reference to an object of type T	 */	void push_front(const T& o);	/**	 * Insert an item in the list before the item pointed to by the specified iterator.	 * \param i An iterator pointing to the item to insert before	 * \param o The item to insert before iterator i	 */	void insertBefore(iterator& i, const T& o);	/**	 * Insert an item in the list after the item pointed to by the specified iterator.	 * \param i An iterator pointing to the item to insert after	 * \param o The item to insert after iterator i	 */	void insertAfter(iterator& i, const T& o);	/**	 * Erase the element at this iterator.	 * \param i A const reference to an iterator object	 */	void erase(iterator& i);	/**	 * Erase a list element.	 * \param pos The position of the element to erase 	 */	void erase(unsigned int pos);};} // namespace util#endif





[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Quote:Still didn't work.

Since they're static members, you need to declare them immediately after your class definition in the header file. Try this instead :
class IMBase{    // class definition ^^};util::list<IMBase*> IMBase::activeList;		///< The list of active objects (with ref_count > 0)util::list<IMBase*> IMBase::deadList;		///< The list of dead objects (with ref_count == 0)
- stormrunner
Okay, its a problem with the list, and not the IMBase, becuase when I declared a util::list<int> object, I got the same 2 errors, just with an int template.

I just noticed that whenever I compile this, the list header file doesn't show up on the list of dependencies, like all the other header files. It looks like I'm compiling the source, but there's no class definition, even if I add "#include "util\list.h" " to the main source file.
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Well, now I'm thinking it has to do with the way that I'm compiling the templated files, because I have a dynamic array "array<T>", and I've added that the way it should be, and I get problems with that as well. One different thing is that "array.h" actually comes up in the external dependencies, with all the other header files.

[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Static member variables don't have to be declared in header file, the source file works fine.
Have you made a default constructor for the list class? The linker errors tell that the constructor hasn't been found.

This topic is closed to new replies.

Advertisement