.:: Bots United ::.

.:: Bots United ::. (http://forums.bots-united.com/index.php)
-   General Programming (http://forums.bots-united.com/forumdisplay.php?f=25)
-   -   C++ overriding methods using virtual (http://forums.bots-united.com/showthread.php?t=2023)

Cheeseh 20-06-2004 22:13

C++ overriding methods using virtual
 
alright, call me a blind man or getting too old for this now... but...

I have a class which is a subclass of another
the super class has a virtual method called action()
and the sub class has a non-virtual method also called action() with the same parameters.

Now, when I invoke the action() method on an instance of the subclass, it should call the overidden method (the one in the subclass) and NOT the one in the super class, right?

Well not in this situation, WHY!!?

My SuperClass...
Code:

class CBotCvar
{       
public:
...

        virtual eBotCvarState action ( CClient *pClient, const char *arg1, const char *arg2, const char *arg3, const char *arg4 )
        {
                return BOT_CVAR_ERROR;
        }

...
};

My SUB class...
Code:


class CBotMenuCommand : public CBotCvar
{
public:
    CBotMenuCommand ()
    {
        this->CBotCvar::CBotCvar("bot_menu",8,FALSE);
    }
       
        void showHelp ( edict_t *pEntity )
        {
                BotMessage(pEntity,0,"bot_menu command help");
        }
       
        eBotCvarState action ( CClient *pClient, const char *arg1, const char *arg2, const char *arg3, const char *arg4 );
};

its method...

Code:

eBotCvarState CBotMenuCommand :: action ( CClient *pClient, const char *arg1, const char *arg2, const char *arg3, const char *arg4 )
{
        //edict_t *pEntity;
       
        if ( pClient == NULL )
        {
                BotMessage(NULL,0,"This command can only be used on the client");
                return BOT_CVAR_ERROR;
        }
       
        //pEntity = pClient->GetPlayer();
       
        gBotGlobals.m_Menus[BOT_MENU_BOT_MAIN].Render(pClient);
       
        return BOT_CVAR_ACCESSED;
}

Calling the method...

Code:

iState = gBotGlobals.m_CurrentHandledCvar->action(pListenServerClient,arg1,arg2,arg3,arg4);
gBotGlobals.m_CurrentHandledCvar is a "CBotCvar*" variable.

Now even though it's a CBotCvar variable it should call the overridden one, because I add a new CBotMenuCommand() to the list of commands which is taken as a CBotCvar* so I can have a heterogeneous list. So it should call the action() method of CBotMenuCommand... BUT it doesn't Argh!

It always calls the crappy method in the super class which does nothing and just returns an error!

Can any one help? I know in Java this would work fine... but C++ is starting to annoy me now :'(

sfx1999 20-06-2004 22:32

Re: C++ overriding methods using virtual
 
Is it a problem with function overloading? I mean you have one as a virtual and one as a non-virtual.

@$3.1415rin 20-06-2004 22:36

Re: C++ overriding methods using virtual
 
Pretty difficult to understand other ppls oo coding problems I have to admit

If you have an instance of your superclass, but a pointer to the base class, and the function is defined virtual in the base class, the function of the superclass is called, even if it may not be virtual in the super class. If you wanna explicitly call the one of the base class, you need to add an additional scope or however this operator is called. so pointer->CBotCvar::action would call the base class function.

Cheeseh 21-06-2004 01:16

Re: C++ overriding methods using virtual
 
I want to implicitly call the sub classes method, which should be done by default! But it's not, I am wondering if I am invoking the method correctly or have specified the correct parameters okay etc. There is no parameter overloading...

even if they are both defined as virtual they don't work

Cheeseh 21-06-2004 01:40

Re: C++ overriding methods using virtual
 
lol!

Found my problem...

Anyone know how to call super class constructor WITHOUT messing up the bloody class???

Check this test program I made...

Code:

#include <stdio.h>

class CSuperClass
{
public:
        virtual void override_me ()
        {
                printf("WRONG METHOD CALLED...WTF???\n");
                return;
        }
};

class CSubClass : public CSuperClass
{
public:

        // mess_up is true, it will call the super classes constructor on me
        // it isn't very useful in this case, but is very useful in other cases
        CSubClass(bool mess_up)
        {
                if ( mess_up )
                        this->CSuperClass::CSuperClass();
        }

        void override_me ()
        {
                printf("CORRECT METHOD CALLED...WOOOT!!!\n");
                return;
        }
};

int main ( int argc, char **argv )
{
        CSuperClass *pInstance1 = new CSubClass(false);
        CSuperClass *pInstance2_messed = new CSubClass(true);

        pInstance1->override_me();

        pInstance2_messed->override_me();

        delete pInstance1;
        delete pInstance2_messed;

        return 1;
}

You'll see that when you initialise when calling the super classes constructor messes up the class for some reason or another...

Now I need to make my own method to initialise instead of calling the super class constructor....

...

stefanhendriks 21-06-2004 09:03

Re: C++ overriding methods using virtual
 
hmm yes thats bummer. I don't like constructors/destructors anyways. I always used my own init() functions in a class. I wonder how this will work if both classes have the same init() functions.. :)

botmeister 21-06-2004 10:01

Re: C++ overriding methods using virtual
 
Maybe I've stayed up too late again, but my understanding of classes is as follows:

The derived class constructor must call the base class constructor before anything is initialized in the derived class. If you have not declared any constructors, the compiler will insert default constructors for you and call them in the proper order. In your case, you have defined a declared constructor, but the same rule applies - the base class constructor always get called before the derived class constructor (the rule makes perfect sense if you think about it).

If you declare a constructor in a derived class, you must call the base class constructor as follows which holds the initilization rule in place:

CSubClass::CSubClass(bool mess_up) : CSuperClass()
{


if ( mess_up )
this->CSuperClass
::CSuperClass();
}

In your case you did not specify the base class constructor, but the compiler will call it for you anyway before CSubClass is called.

When mess_up evaluates to true, your code is attempting to call the base class constructor twice and improperly (which is why you are resorting to using this)!
You cannot prevent a class from executing its constructor, and if you manage to do it, your class will not initialize properly.

One more note about all this, the base class constructor should not make use of variables from the derived class (via a virtual function call) because they won't be initialized until after the base class constructor call is completed. Generally, the compiler will initialize these variables to zero (or null) beforehand anyway, but this is not a rule that can be relied on.


Whistler 21-06-2004 11:25

Re: C++ overriding methods using virtual
 
I think it's a bug of MSVC since that's actually INVALID, and that test program doesn't compile in GNU GCC and Borland C++ at all:
Quote:

C:\>gcc 1.cpp
1.cpp: In constructor `CSubClass::CSubClass(bool)':
1.cpp:22: parse error before `;' token

C:\>bcc32 1.cpp
Borland C++ 5.6 for Win32 Copyright (c) 1993, 2002 Borland
1.cpp:
Error E2316 1.cpp 22: 'CSuperClass' is not a member of 'CSuperClass' in function
CSubClass::CSubClass(bool)
Warning W8057 1.cpp 45: Parameter 'argc' is never used in function main(int,char * *)
Warning W8057 1.cpp 45: Parameter 'argv' is never used in function main(int,char * *)
*** 1 errors in Compile ***
also I think if the constructor of base class if NOT virtual it will automatically get called before the constructor of sub class gets called.

Cheeseh 21-06-2004 11:58

Re: C++ overriding methods using virtual
 
Thanks anyway, but I sorted the problem anyway by making my own setup() ( initialise method) instead of using the constructors, (as stefan said too :p). But it's a bizzare problem anyway...

In my bot code, I tried the same as...

CSuperClass::CSuperClass() instead of this->CSuperClass::CSuperClass()

And a problem arises there when you want to initialize stuff, it doesn't actually change the stuff you want to initialize...

@$3.1415rin 21-06-2004 16:02

Re: C++ overriding methods using virtual
 
with that virtual functions, I guess you somehow got the sense of them wrong. a virtual function from a super class where the function exists in a subclass will never be called, unless you declare it explicitly like stated above. the whole virtual stuff wouldnt make much sense if you couldnt have a pointer to a base class and then without knowing what type of element it is, calling that function. depending if the instance is some subclass with its own function, or only the super class, the appropriate function will be called.

and it's also maybe a naming problem here. So you call e.g. all those BASE class in the HLSDK mainly superclasses, derived classes subclasses, right ? There is a lot of naming differences around, so that's maybe a problem too

and about constructors : yes, you have to get clear to see when which constructor gets called, but then it's advisable to use them to avoid initializing twice or even more. and the calling of constructors with this type of class config makes sense, since you want only to initialize the member variables. Sometimes it's getting a bit scary when you have no default ctor, but well, then you just have to do it via a : and then the base constructor with the arguments.

like this e.g. :
Code:

class CBV_HLDM_HideReload:public CBehaviour,CCallback_onPathCreation,CCallback_onReachedDestination{

public:

CBV_HLDM_HideReload(CBaseBot *pBot):CBehaviour(pBot){strcpy(m_szName,"CBV_HLDM_HideReload");}


botmeister 21-06-2004 18:19

Re: C++ overriding methods using virtual
 
Quote:

Originally Posted by Cheeseh
Thanks anyway, but I sorted the problem anyway by making my own setup() ( initialise method) instead of using the constructors, (as stefan said too :p). But it's a bizzare problem anyway...

In my bot code, I tried the same as...

CSuperClass::CSuperClass() instead of this->CSuperClass::CSuperClass()

And a problem arises there when you want to initialize stuff, it doesn't actually change the stuff you want to initialize...

I'd say you have not sorted the problem out, but instead found a work around.

In general, you cannot get away without the use of constructors/destructors if you want to use some of the more advanced features provided with classes.

It is possible there's a problem with the MVC compiler, but more likely the problem lies elsewhere, since it is absolutely neccessary that constructors/destructors work flawlessly, at least when used as intended (or expected).

Cheeseh, perhaps I do not understand what is going wrong. Can you show me another example, or give me more details? Does the problem go away without the use of the virtual function?

ps: I'd like to see your "normal" code that does not work as expected, not the code with the attempts to get around the problem - thanks :)

Cheeseh 21-06-2004 18:36

Re: C++ overriding methods using virtual
 
I need a virtual function so I can override it with sub-class methods.

Sure I worked around the problem, that's good enough :P

It was because I had that constructor call to it's super class inside the sub class' constructor, it mucked up the class in some way (almost turning it into the superclass class...).

I guess that the definition that you showed earlier...

CSubClass :: CSubClass () : CSuperClass()
{
...
}

was a better way of doing it but I haven't tried that since I'd rather stick to my current method... but whenever I need to do this again, I'll try it like that :P

The normal code is just a list of bot commands, a list of "CBotCvar"'s (which is the super class) and each subclass is a unique command... e.g. bot_menu (shown earlier). It has it's own action() function which does its stuff.

The super classes action method is virtual and it does nothing. So that when I look through the list and call the bot_menu "CBotCvar" action() method, it should call CBotMenuCommand's action() to do its business.

I need the action function in the superclass so I can compile it! And I need it to be virtual so that it will call the appropriate action() method of the subclass if I wrote one for the subclass.

botman 22-06-2004 01:03

Re: C++ overriding methods using virtual
 
In your original post, you said...

" gBotGlobals.m_CurrentHandledCvar is a "CBotCvar*" variable."

Which means you are declaring pointers to the base class and then trying to call virtual functions from the derived class (which won't happen without you doing some run-time dynamic casting on the pointer).

Why didn't you just make 'm_CurrentHandledCvar' a pointer to 'CBotMenuCommand' instead of a pointer to the base class?

Cheeseh 22-06-2004 02:25

Re: C++ overriding methods using virtual
 
oh man... the confusion :)

The current "CVAR" is updated when a player enters a client command of a valid bot command. The valid bot command will be a pointer to a subclass instance of CBotCvar.

All the valid commands are held in a list of CBotCvar pointers. I need this as this is the only way to have a heterogeneous list of objects (eg. vector<CBotCvar*> m_BotCvars for the list).

I cannot make a list of completely different objects using OO methods, I don't think so anyway.

When the CBotCvar is matched by the cvarname (a string held in the CBotCvar class) it will call the action method. If the retrieved instance is derived from the CBotCvar class it will call it's own action method if it exists, so it will do it's own stuff. (e.g. If the retrieved CBotCvar* pointer from the list is derived from CBotMenuCommand class, it will call CBotMenuCommand 's action() method)

I'm sure this is the basic stuff of OO dynamic dispatching... certainly in Java, much stuff in Swing is done like this.

;) believe me, it works!!! ;)

(I've updated my bot source on my site with the stuff... bot.h/bot_commands.h/bot_commands.cpp has the stuff)

@$3.1415rin 22-06-2004 10:11

Re: C++ overriding methods using virtual
 
that should work when declaring the function virtual in the superclass .. well, i'll download that files and see :D

So that files that are there at the moment do _not_ work as supposed to, right ?

Cheeseh 22-06-2004 12:53

Re: C++ overriding methods using virtual
 
They actually DO work as supposed to... If you put in that constructor thingy where it called the super class in each subclasses constructor, then it will muck it up entirely :/


All times are GMT +2. The time now is 05:50.

Powered by vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.