Some help with classes.

Started by
3 comments, last by KuroKitten 17 years, 11 months ago
I'm trying to make a LinkList class for my program. I've done this recently using Java, however I'm fairly new to C++ classes, and I'm having trouble. The general method I used in Java was as follows: Create a "LinkList" class. LinkList has a ListNode object with some value in it. ListNode also contains in itself another ListNode set to NULL. If I want to add another element, I just set the ListNode object to a value. That new ListNode also has a NULL ListNode object. You do the same thing on down the line. Once you get that working, setting up functions to move around, replace, delete and add nodes is pretty easy. I'm currently having problems doing the following method in C++. Here's what I've gotten together so far... MapNode.h

class	MapNode
{
	private:
		MapNode nextNode;
		Texture nodeTexture;
		

	public:
			MapNode( Texture tempTexture );
};
MapNode.cpp

#include "MapNode.h"

MapNode::MapNode( Texture tempTexture )
{
	nodeTexture = tempTexture;
}
I'm doing this to make a linked list of Textures (a class I also made; just contains a "texture" block and a function to draw it). Right now the compiler is telling me it doesn't like the type Texture or MapNode in MapNode.h Also, texture does work without errors. I use it in my main.cpp without errors. Like I said, I'm really new to C++ classes, so I'm sure I'm making a stupid, yet obvious mistake ^^; Also, this is an on-going project, so as one problem gets fixed, another is likely to come up. As long as it still pertains to my LinkList, I'll just keep updating. Meow.
Advertisement
First things first. Writing a linked list for learning purposes is a very sensible and worthwhile thing to do. However, once you've written said linked list implementation throw it away. The C++ standard library already contains an efficient, error-free linked list class: std::list. When you come to actually wanting to use a linked list instead of learning how to write one use the standard version (#include <list>).

On to your problems. Java and C++ differ in how they handle variables. Java uses reference semantics, with the exception of the primitive types, which means everything is a reference and the code:

Object object1 = new Object();
Object object2 = object1;

results in the variables object1 and object2 referencing the same piece of memory. In C++ you have the choice between using value semantics and reference semantics. In C++ the code:

Object object1;
Object object2 = object1;

results in the variables object1 and object2 being two separate pieces of memory with equivalent value. The alternative code:

Object * object1 = new Object();
Object * object2 = object1;
delete object2;

is more similar to the Java code and the variables object1 and object2 reference the same piece of memory. Note one fundamental difference between C++ and Java though - in C++ you have to do memory management yourself and explicitly delete what you new.

Now lets look at your code:
class MapNode{	private:		MapNode nextNode;		Texture nodeTexture;	public:		MapNode(Texture tempTexture);};

The first problem is that MapNode contains another MapNode by value. This is impossible in much the same way as storing a 1m×1m×1m metal box inside another 1m×1m×1m metal box is impossible. Even worse the MapNode that is inside this MapNode will contain a further MapNode, which will contain yet another MapNode, ad infinitum.

The solution is to use reference semantics:
class MapNode{	private:		MapNode * nextNode;		Texture nodeTexture;	public:		MapNode(Texture tempTexture);};

To continue the metal box analogy this is like having a 1m×1m×1m metal box which contains a piece of paper describing where to find another 1m×1m×1m metal box, which is obviously easier to do than storing identical boxes inside each other.

You may have seen the pointer there, remembered about memory management and wondered where to put a delete statement. This is where you must be most careful. Every object that was allocated by new must be deallocated by delete exactly once. Deallocate it zero times and you have a memory leak. Deallocate it more than once and you have undefined behaviour, which, if you're lucky, means you program will crash immediately or, if you're unlucky, will mean that you program will appear to work perfectly for a long time until the one point where you absolutely need it to work, at which point it will crash.

In general you should try to work out which piece of code owns a particular object which was allocated by new and this piece of code should be solely responsible for deleteing that object. In this case that piece of code is probably your linked list implementation. Even more generally you should try to avoid manual memory management at all by using prewritten classes that handle memory for you like the standard container classes (including the aforementioned std::list).

You said you also had a problem with your compiler complaining about the Texture class. Unlike Java, C++ won't go searching through all your source files to find what a class is. When it compiles MapNode it needs to know the structure of a Texture so that is can build MapNode big enough to fit a Texture inside. In order to give it enough information about Texture you need to #include "Texture.h" before the MapNode class definition (i.e. at the start of MapNode.h).

Σnigma
I have two new questions:

1) I've been having trouble finding information about the C++ standard list class. I'm not sure exactly what syntax to use after I've included it ^^;

2) Is there a way to refer to a general object? Like, rather than haveing a "Texture nodeTexture;" I would do something similer, but make it so they could make a linked list of any variable type or Class. Or is this not possible?

Meow.
Quote:Original post by KuroKitten
I have two new questions:

1) I've been having trouble finding information about the C++ standard list class. I'm not sure exactly what syntax to use after I've included it ^^;

2) Is there a way to refer to a general object? Like, rather than haveing a "Texture nodeTexture;" I would do something similer, but make it so they could make a linked list of any variable type or Class. Or is this not possible?

Meow.


1) http://www.msoe.edu/eecs/cese/resources/stl/list.htm

2) There are two ways you can go about doing this. One is with a void* pointer, which I highly don't recommend. The other way is with templates, what they do is automatically "code" in every possible type of data type/class/struct that could be put as a type. For example:

template<typename T>class	MapNode{	private:		MapNode* nextNode;		T nodeData;	public:			MapNode( T tempData ) : nextNode(NULL)                        {     nodeData = tempData;     }};MapNode<int> MapNodeOfInts;MapNode<Texture> MapNodeOfTextureClasses;


It's that simple. The compiler will automatically code for every possible combination in the program.
We should do this the Microsoft way: "WAHOOOO!!! IT COMPILES! SHIP IT!"
Wow, I'm really learning a brainfull with this XD

Alright, well I have absolutly zero experience with tamplates. I can understand the general idea based on how it's used in the code you provided. However, this is far from understanding them >.>" My newest error pertains to that.

MapNode.h
//Code helpfully provided by dbzprogrammer on the GameDev.net forums #include <cstdlib>template<typename T>class	MapNode{	private:		MapNode* nextNode;		T nodeData;	public:			MapNode( T tempData ) : nextNode(NULL)                        {     nodeData = tempData;     }    void 	setNext( MapNode newNext );};


MapNode.cpp
#include "MapNode.h"void MapNode::setNext( MapNode newNext ){		nextNode = newNext;}


and this is the error it's giving me:
3 F:\Main\Programming\Solice\MapNode.cpp `template<class T> class MapNode' used without template parameters
3 F:\Main\Programming\Solice\MapNode.cpp variable or field `setNext' declared void
3 F:\Main\Programming\Solice\MapNode.cpp missing template arguments before "newNext"
4 F:\Main\Programming\Solice\MapNode.cpp expected `,' or `;' before '{' token

(that is the error provided using Dev C++)

I kind of understand what it's getting at. I know when I make a MapNode I need to do something like this: MapNode<int> someNode; It's wanting me to have something similer to the <int> part. I'm not quite sure how I should include that in my function though... MapNode<T>? Or is MapNode<void> something perhaps? I'm mostly just guessing though ^^

Mew.

Edit:

I looked around about Templates, and figured out how to use them a little better. I needed to include a "template<typename T>" before each function and put a "<T>" before instances of MapNode.

[Edited by - KuroKitten on May 25, 2006 10:40:24 PM]

This topic is closed to new replies.

Advertisement