.:: 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");}



All times are GMT +2. The time now is 08:47.

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