Deriving but keeping data

Started by
17 comments, last by Tallkotten 11 years, 8 months ago
Hello!

About a week ago i posted on this forum asking for help with a pointer problem. People were very helpful and gave me loads of tips to read up on.

So this week i've been reading like crazy and i am ready to basically re-write my project. I still doesn't know how to solve one thing thought.

At the moment i have a loader class which basically loads in images, fonts and eventually sounds. Every class is derived from this one. But as someone pointed out in the previous thread that must mean that all the files are loaded several times since the actual loading takes place in the constructor.

So for every class that's being made it must contact that constructor again and re-load everything.

I've gotten some tips from my dad and one was to make a static function and variable of the class to make sure it only loads once. He showed me an example of how to make it work. I'm just wondering how you guys tackle this problem and if static is the way to go or if there are several ways to do this!

Thank in advance!
Advertisement
`static' is rarely the way to go. I don't quite understand your situation, but "Every class is derived from this one" sounds like a horrible design in pretty much any circumstance.

I don't know what other thread you are talking about. You should make this one self contained, if at all possible. What exactly is your design?
You may need to separate you classes more. One class is for containing the loaded data, a separate class for instances of that data. Objects of the 'instance class' contain state about the individual instances (say, position and life points) and a pointer to the loaded data that contains data such as bitmaps.

Stephen M. Webb
Professional Free Software Developer

I am separating my classes, that is why i'm redesigning the program.

But image this. The class loads an image for a grass tile as well as the player model.

Both classes needs to be able to access their variable(image). But both the tile and player class is already derived from other classes.

How do i get them (without sending the class Loader to their class via a function) to access the same class and have access to draw out images from the same selection of variables.

I basically need the loader function to only exist in one copy, so that i never recreates itself.

I know i could solve this by sending the adress via a pointer to all the classes i create. But it just seems like a hassle if there is a simpler way.
You might want to post some code that demonstrates exactly what you're doing, both with and without the static.

I basically need the loader function to only exist in one copy, so that i never recreates itself.

If your loader needs state, or provides a virtual interface, you will need to pass it to your object constructors, because they need it. As simple as possible, but no simpler.

If your loader does not need to track its own state, or if it consists of a single static interface, you have yourself a factory function. It does not need to be a member of a class, it's better to have it as a namespace-level function.

It sounds to me (and I'm just guessing) that you want to pass a factory object (a "builder") to your object constructors. The factory object caches the loaded tiles and doles out a pointer to the loaded tile to each instance that asks for it.

Perhaps something like this.
[source lang="cpp"]
class Tile { /* ... */ };

class TileFactory
{
public:
Tile* get_tile(std::string const& tile_name)
{
if (cache_.find(tile_name) == cache_.end())
{
cache_[tile_name] = load_tile(tile_name);
}
return cache_[tile_name];
}
private:
std::map<std::string, Tile> cache_;
};

class ObjectBase
{
public:
ObjectBase(TileFactory& tile_factory, std::string const& tile_name)
: tile_(tile_factory(tile_name))
{ }
virtual ~ObjectBase()
{ }
protected:
Tile* tile_;
};

class BackgroundObject: public ObjectBase
{
public:
BackgroundObject(TileFactory& tile_factory, std::string const& tile_name)
: ObjectBase(tile_factory, tile_name)
{ }
};

int main()
{
TileFactory tile_factory;

BackgroundObject grass(tile_factory, "grass");
BackgroundObject house(tile_factory, "house");
}[/source]

If you need a whole clot of such factories, you can combine them into a single [font=courier new,courier,monospace]struct[/font] and pass that through, too.

Stephen M. Webb
Professional Free Software Developer


You might want to post some code that demonstrates exactly what you're doing, both with and without the static.


Right now i don't have any code except a class with variables that gets initiated when the constructor runs.

I am asking this since i need help creating the class i need.
But here is some code for example:

Imagine that these classes are located in different files as well!


Class Loader
{
public:
Loader()
{
SDL_Surface* tile = IMG_Load("tile.png"); //img_load is my own func
SDL_Surface* player = IMG_Load("player.png");
}
SDL_Surface* tile;
SDL_Surface* player;
}


Class Tile: public Loader
{
public:
Tile();
draw(SDL_Surface* screen)
{
//draw out the image tile from Loader
}
}


Class Player: public Loader
{
public:
Player();
draw(SDL_Surface* screen)
{
//draw out the image tile from Loader
}
}


main
{
init()
{
Loader loader;
Tile tile;
Player player;
}
draw
{
tile.draw();
player.draw();
}

init();
draw();
}


In that case isn't tile and player variables inside Loader being created twice. Once for class Tile and once for class Player?
Class Player: public Loader[/quote]
I assume you meant `class', and not `Class'. But besides that, I think that line is the essence of your problem. To me that line reads "Player is a Loader". It means that anywhere I would you a Loader, I could use a Player instead, because Player is a type of Loader. If that doesn't sound right to you, neither should the line of code I quoted.

IMHO, people get exposed to inheritance too early when they are learning programming, so they think it's the way you do everything. You probably don't need inheritance at all in this situation. If a Tile and a Player need access to a Loader for some reason (although I wouldn't do it that way either), they should each have a member function that is a pointer to the Loader, and this should be set in the constructor.

Class Player: public Loader

I assume you meant `class', and not `Class'. But besides that, I think that line is the essence of your problem. To me that line reads "Player is a Loader". It means that anywhere I would you a Loader, I could use a Player instead, because Player is a type of Loader. If that doesn't sound right to you, neither should the line of code I quoted.

IMHO, people get exposed to inheritance too early when they are learning programming, so they think it's the way you do everything. You probably don't need inheritance at all in this situation. If a Tile and a Player need access to a Loader for some reason (although I wouldn't do it that way either), they should each have a member function that is a pointer to the Loader, and this should be set in the constructor.
[/quote]

Yeah, i mane class.

That's my old code. Like i said i am re-writing it all now. Had inheritage on way to many places. So i'm currently in a process of fixing LOADS of newbi errors
Ok, but is it any other way to solve this than so send it to the constructor? or i that the way to go?
What about something like this:

type Loader
{
def Image load(string name) { /* ... */ }


private Cache<Image> cache;
}

type Tile
{
def Tile(Loader loader)
{
image = loader.load("tile");
}


def draw(Screen screen)
{
screen.draw(image);
}

private Image image;
}

type Player
{
def Player(Loader loader)
{
image = loader.load("player");
}


def draw(Screen screen)
{
screen.draw(image);
}

private Image image;
}

def main()
{
Loader loader = new Loader();
Tile tile = new Tile(loader);
Player player = new Player(loader);


// ...

tile.draw(screen);
player.draw(screen);
}

This topic is closed to new replies.

Advertisement