leave function definition "empty" (c++) ?

Started by
11 comments, last by Krohm 9 years, 2 months ago

Hi

I have a general class handling inventories in my game engine (c++)

It has a function getItemNames:


char * gameInventoryMaster::getItemName(gameItem * uu)
{
	if(useSpecialNames)
		return getSpecialItemName(uu);
	else
		return IDATA[uu->type].name;
}

The getSpecialItemName is just declared in the general engine class, not defined.

Instead it is defined in each game separately (because some games may have diablo-like item modifiers that affect name, while others affect item names in another manner etc).

Problem is its unpractical to be forced to define that function in all games using the engine (some games dont use inventories or at least not specialItemNames).

If i dont add a definition i get compiler errors (fatal error LNK1120: 1 unresolved externals). I want to leave it "empty" (not there) if i dont use it. Is it not possible in c++?

Thanks
Erik

Advertisement
What do you want to happen if somebody calls this `"empty" (not there)' function?

Also, you probably should be using std::string instead of raw pointers to char. The ownership issues with returning pointers to char are a nightmare. And getItemName should probably be a const member of gameInventoryMaster and take a const pointer to gameItem, since I don't expect it to make changes to either of those things.

Im fine with crashing if calling an "not there" function. Its either used or not used for an entire project so its not gonna be a problem.

Or returning the string "NO NAME" if its possible to define a default function should there not be anyone defined.

I presume this function is declared virtual? If so, what you need is a pure virtual declaration (use " = 0" after the declaration), and no definition:


class Base
{
    virtual void FunctionThatIsEmptyInBase() = 0; //will fail without = 0, since it isn't defined anywhere
};

class Derived : public Base
{
    virtual void FunctionThatIsEmptyInBase(); //add the override keyword before the semicolon if using C++11 or later
};

void Derived::FunctionThatIsEmptyInBase()
{
}

A pure virtual function marks the entire class as pure virtual, which means it can never be instantiated. Any class that derives from a pure virtual base class must provide implementations for all pure virtual functions, or else it too cannot be instantiated, and must be further derived with remaining pure virtual functions implemented someone down the chain.

"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke
Given more context, there might be a more graceful solution, but as it stands it sounds as though you are just annoyed that the engine begs you to fill in a blank every time you inherit from a certain class.

In that case, create a single class that fills in all those blanks (the names, etc.) and instead of later deriving from the original class, derive from your new class.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

You could also provide a default implementation of the virtual function that generates a runtime error. That way you can create subclasses that don't implement the function, and it will work fine as long as nobody calls it.

Still, the whole design stinks a bit... If a class inherits publically from another one, I would expect it to implement the whole interface.

I agree that the broader strokes of this design smell funny, I would encourage OP to consider a different line.

But, ignoring that for now and dealing with the problem at hand, I think what'd I'd do is make getSpecialItemName a function pointer, and set it to a default implementation. For a game to override this function, what they would do is create their own function with a compatible signature, and then set the getSpecialItemName function pointer to point to their function. This is basically implementing one-off virtual inheritence, though, and if you're implementing this all in C++ (but looks like you're using C, maybe?) you'd be better off just using the facilities provided by the language.

If you take this approach, do provide a default function, even if what it does is force the program to exit with an error code (because its an error for the client to call getItemName with an ID that invokes getSpecialItemName when it has not been provided). You could say "If the function pointer is null, then skip it." but then A) you'd have to check at every call site, and B) what would you then return anyways? To be clear, there's nothing preventing client code from setting the function pointer to null, so this doesn't prevent that error, but giving it a non-null default makes later assigning it one an explicit error.

throw table_exception("(? ???)? ? ???");

Ravyne, the title of the thread says he is using C++, and I don't think the :: in the code means anything in C.

The need for adding dummy methods is a clear sign of a bad OO design. If a method is not useful in any and all of the derived classes then it should not be in the base class.

Therefore you would be better off correcting this design blunder by deleting it from your "engine" class.

You should also consider not using inheritance as much. Often its simpler to use composition and have complete objects owned and called by some class in your game than to derive from some class and then be forced to find and fill all those gaps.

A better design here would be to make getItemName virtual, with " return IDATA[uu->type].name;" as the default implementation. When a special item name is needed, the user would override this method.

This topic is closed to new replies.

Advertisement