Advertisement

Simple Class Question

Started by June 10, 2000 11:41 PM
9 comments, last by Esap1 24 years, 6 months ago
//Script.h class Commands { public: void Action(); }; class Script { public: Commands Command[20]; void SetCommands(); }; //Script.cpp Script::SetCommands() { How do I set the functin action in a Command element? Like this?? void Command::Action() { } } How can I set the function to be different. I dont want every Action function in the Command Array to be the same. Is there a way I can make them different. Or do I need to put an array of Action functions in the Script class? Sorry if this sounds confusing Thanks a lot every one(I really need to brush up on my C++).
Well I guess the only way it could be done is to Make 1 Big function that took a parameter to what command was to be run. Ill try that.
Advertisement

I''ve done something like this in my engine... I''m using an "IdleApplication" class and you can set your own Idle function to be called every frame.
All you have to do is a pointer to a function:

void (*ptrFunction)();


Then you change the pointer to point over a function:

void FunctionX()
{
...
Commands;
...
}

class.ptrFunction = FunctionX;


And you can call it like a simple function.

class.ptrFunction();


Simple, easy and still fast. You can put return values and arguments, but your function must meet the "pointer requirements". i.e. Return value be the same or compatible, same for arguments...
Now I know what I'm made of, and I'm afraid of it...
I think you mean something like this:
        // Woo, my first time with the source tags *smile*class Script {public:    Commands* Command[20];    void SetCommands();};class Commands {public:    virtual void Action();};class AttackCommand : public Commands {    void Action() { DoAttack(); }}class DefendCommand : public Commands {    void Action() { DoDefend(); }}class WanderCommand : public Commands {    void Action() { DoWander(); }}//Script.cppScript::SetCommands(){    Command[0] = new AttackCommand();    Command[1] = new DefendCommand();    Command[2] = new WanderCommand();    // etc...}        

To execute the command, call Command[x]->Action(); Because the Action() function is virtual, it knows to call the 'right' one.

Note: although this is what I think you were asking to do, consider the function pointer method also, as that will allow you to change things at run time, for example. See if you can understand both methods, then you'll know what's right for you.


Edited by - Kylotan on June 11, 2000 2:07:07 AM
Kylotan: Hey! What''s the tag you used to do code like that?
Now I know what I'm made of, and I'm afraid of it...
If you look at the source code you notice the (source) UBB-tag. Remember to use brackets around source.

    void test(){};    


Sludge Software
www.sludgesoft.com
Developing a secret of mana style role-playing-game
Sludge Softwarewww.sludgesoft.comDeveloping a secret of mana style role-playing-game
Advertisement
oof.. you dont wanna derive a new class for every action, that''s too non-abstract (i''m not talking from the code efficiency standpoint, although that might induce some overhead, its just that this is really not a good programming practice). just use function pointers, setting each instance''s action function to either an existing method or a user defined function.


--
Float like a butterfly, bite like a crocodile.

--Float like a butterfly, bite like a crocodile.
quote: Original post by goltrpoat
that''s too non-abstract ... its just that this is really not a good programming practice


That''s just your opinion. How can it be ''non-abstract'' when you are quite literally calling each function through an abstract interface? Many respected people in the OOP field prefer derived function type objects to function pointers. I direct you to the Command pattern in the Design Patterns book, for example.

Using objects like this, you eliminate the chance of having null function pointers. You allow more than for just the actual function to be stored: for example, what if he wants to display this script? In the object method, you can just implement a Commands::Display() virtual function which can return you the Command''s name and parameters. Using function pointers in a generic Command class, he would have to initialise each instance with the name of the command as well, which is redundant since you already have a pointer to the function.

Now, as I said the first time around, I wouldn''t rule out the use of just function pointers, but the best way will depend on what exactly you want to do with it all.
The real problem in my opinion is that with this kind of practice (inheritance), it will probably results in a "select case" function that could be implemented in the Command function without having extra-code.

With pointer functions, you could even introduce an easy patch for adding script commands... With DLL or even your own format. ((you could implement DLLs with the inheritance too))

But like he said, try to know what you want exactly. In fact, the inheritance version is more C++ and object oriented, while the function pointers are more C...
Now I know what I'm made of, and I'm afraid of it...
quote: Original post by Poltras

The real problem in my opinion is that with this kind of practice (inheritance), it will probably results in a "select case" function that could be implemented in the Command function without having extra-code.


The idea of the inheritance is that it moves that kind of ''select/case'' functionality to behind the scenes. Function pointers are one way of eliminating select statements, and inheritance is the other. I don''t know how most select statements are implemented but the way inheritance in C++ handles it only needs an extra pointer dereference to find the correct function. The performance decrease is less than negligible, if that is what was concerning you?

quote:
With pointer functions, you could even introduce an easy patch for adding script commands... With DLL or even your own format. ((you could implement DLLs with the inheritance too))


Actually, it would be just as easy to patch code into the inherited version. With the pointer version, you need to write the new function, and write code that allows it to be chosen from within Script::SetCommands(). With the inherited object version, you write the new derived class, including the function, and also add the code in that allows it to be chosen. About the only difference is that the inherited version would require access to the base Command class''s header file. But it allows you to easily implement things such as Command::GetName(), Command::GetNumberOfTimesUsed(), Command::Disable(), etc. It really does depend on how much you need a command to be able to do: if you can guarantee that you''ll never need to do more than just execute a function, then a pointer will be fine.

This topic is closed to new replies.

Advertisement