View Single Post
Old 12-31-2003, 10:05 AM   #26 (permalink)
Valmont
[code][/code] enforcer
 
Valmont's Avatar
 
Join Date: Mar 2003
Location: Netherlands
Posts: 1,544
Valmont is on a distinguished road
These are my very last hours (possibly minutes) online. I will be offline for the next two months or so. Then I will be back.

Since you want to program games in the (near) future, I'll give you advice on typical relevant issues (coding wise). I won't be able to do that later.

1) Learn ALL the basics of classes.
- Constructors
- Destructors
- Virtual Destructors.
2) Learn all the basics of derriving classes and what that means.
- Virtual methods (functions).
- Pure Virtual functions.
3) Learn the ways of pointers and references.
- What does the pointer in this function want:
void Function(SomeType* type);
Answer: it wants to receive an adress. Not a variable.

//Scenario One:
SomeType MyFirstObject;
Function( & MyFirstObject); // need ampersand for adress!
//Scenario Two:
SomeType* MySecondObject = new SomeType;
Function( MySecondObject ); // no need for '&' because MySecondObject is a pointer, therefore it hold an adress!
- Can you figure out how it works with arrays? Very simple but try to create something that works.

4) What is this code below doing? (Now we are going to do some real stuff). I will ask typical questions later after the code.

Code:
//**** BaseOne.h ****

#include "ISomeInterface.h"

class BaseOne
{
public:
	void SetIface(ISomeInterface* iface) { delete IFace; IFace = iface;	}

public:
	BaseOne(ISomeInterface* iface) : IFace(iface){}
	BaseOne () : IFace(0) {}
	~BaseOne() { }

private:
	ISomeInterface* IFace;
};

//**** BaseTwo.h ****

#include "ISomeInterface.h"

class BaseTwo
{
public:
	void SetIface(ISomeInterface* iface) { delete IFace; IFace = iface;	}

public:
	BaseTwo(ISomeInterface* iface) : IFace(iface){}
	BaseTwo() : IFace(0) {}
	~BaseTwo() { }

private:
	ISomeInterface *IFace;
};

//**** ISomeInterface.h ****

#ifndef ISOMEINTERFACE_H
#define ISOMEINTERFACE_H

class ISomeInterface
{
public:
	ISomeInterface() {}

private:
	ISomeInterface& operator=(const ISomeInterface&){}
	ISomeInterface(const ISomeInterface&) {}
	
};


#endif // ISOMEINTERFACE_H



//**** Main.cpp **** Our entry point for the app.

#include "BaseOne.h"
#include "BaseTwo.h"
#include "ISomeInterface.h"
#include <iostream>

using namespace std;

int main()
{
	/*
	BaseOne(new ISomeInterface);
	BaseTwo(new ISomeInterface);
	*/
	

	/* 
	ISomeInterface* IF = new ISomeInterface;
	BaseOne B_1 = IF;
	BaseTwo B_2 = IF;
	delete IF; //*/

	/* 
	ISomeInterface* IF = new ISomeInterface;
	BaseOne B_1;
	BaseTwo B_2;
	B_1.SetIface(IF);
	B_2.SetIface(IF);
	delete IF; //*/

return EXIT_SUCCESS;
}
Phew!
Ok.
1a) Do you know what this is good for: BaseOne(ISomeInterface* iface) : IFace(iface){}
1b) This does the same (but not automatic like a constructor): void SetIface(ISomeInterface* iface) { delete IFace; IFace = iface;}
Answer: This is a 'plug-in' system. The user can plug-in ISomeInterFace in class BaseOne or BaseTwo. Look at main() on how it is done. This standard technique is most important for some decent OO programming and applies to certain areas of the gamingworld.
2a) Now look very closely to this code below:
private:
ISomeInterface& operator=(const ISomeInterface&){}
ISomeInterface(const ISomeInterface&){}
2b) Why is my copy-constructor 'private'(normal = public), and not even implemented?
2c) Why is the operator= method private and not even implemented?
Hint: look for "private copy constructor" or something like that, on the net. Or in a a VERY good book.
2d) I have at least one pointer in my BaseOne and BaseTwo classes, but I left the destructors empty. Why?
Hint: He who creates, destroys.
2e) Look at the code:
"void SetIface(ISomeInterface* iface) { delete IFace; IFace = iface;}"
What is the "delete" operator doing there? It deletes, I know. But why there, just before IFACE receives a new value?
Hint: Potantial leak somehow?
3) Your task (very important!)
- Derrive two classes from ISomeInterface.
- Make ISomeInterFace an 'abstract' class.
Hint: make this a PURE VIRTUAL FUNCTION:
void SetIface(ISomeInterface* iface) { delete IFace; IFace = iface;}
You know how to do that? You know what that means for your two derrived classes?
- In main() : Instead of 'plugging' an instance of ISomeInterFace in BaseOne (or BaseTwo), plug a derrived class from ISomeInterface in BaseOne or Base two.
4) Do you know what you were doing?
Hint:
- You made two machines (BaseOne and BaseTwo). They achieve the same thing but do it differently.
- You made two modules (the two derrived classes from ISomeInterface) for these machines. For example you can put DerrivedIFace_1 OR DerrivedIFace_2 in an instance of BaseOne. You can plug it in.
MORE HINTS:
- BaseOne is a vehicle in a game. (game, hint hint).
- BaseTwo is another vehicle in a game. Perhaps a vehicle with more weapons.
- "DerrivedIFace_1 : ISomeInterFace" ( our first derrived class) is a certain strategy. We can load it in one of or both the types of vehicles. For example, let a vehicle play cautiously. Or load "DerrivedIFace_2 : ISomeInterFace" in one or both the types of vehicles (BaseOne and BaseTwo, remember?) so they play more agressivly.
5) Do you realize that BaseOne and BaseTWo (our different fight-vehicles) only know they can receive modules of "ISomeInterface". The fight-vehicles don't know anything about possible strategies they gonna get (DerrivedIFace_2, ... ). Can you explain that to your self and others why?
6) Do you realize the Interface classes don't know anythihg at all? They are a completely "stand-alone" items. That is OO. Can you convine yourself?
7) You want 10 types of fight-vehicles instead of only two. Perhaps one is slow and weak and cheap. The best one is fast and powerfull and expensive. How you gonna solve this the OO-way?
Hint:
- Rename our BaseOne and BaseTwo to "DerrivedOne" and "DerrivedTwo".
- Make a baseclass called "Base". Make it an abstract base class for
DerrivedOne and DerrivedTwo. Or in other words, make sure DerrivedOne and DerrivedTwo are derrived from abstract class "Base".
- Now what you have to do is implement a typical "void Print()" method for DerrivedOne and DerrivedTwo, AND one for class "Base". So base hold the pure virtual method: "virtual void Print() = 0;"
And DerrivedOne holds "virtual void Print() { cout<<"Cheap Vehicle attacks!!!<<endl;}"
Don't forget to make another one for DerrivedTwo...

Now I want you to make a thing happen like this:
int main()
{
DerrivedIFace_1 IF_1; //get a strategy ready
DerrivedTwo DT; //get a fight-vehicle ready
Base* B = DT; //Load an abstract vehicle with a fight-vehicle (see line below)
B->Print( & IF_1 ) // Attaaack (Print) with strategy IF_1!
}

See what I am getting at? This is real OO. Not what is described in the beginner books or intermedate books.
Make sure you can do the task I given to you. It is the very very very basics of OO. But if you can do it with my code, then you rock and are ready to move on. Just find a way to test your code.

Good luck!
- Val -
__________________
Valmont is offline   Reply With Quote