Thread: Problems with virtual function calls, please help

  1. #1
    Registered User
    Join Date
    Jan 2007
    Posts
    54

    Problems with virtual function calls, please help

    Hello,

    I have been working on a few classes for a 2D gui system and I have a really wierd problem that I have spent days trying to work out and I really don't know what is wrong.

    I have a cGUIManager class, a cBaseWindow class from which window classes are made using inheritance, then Windows have controls, so I have a cBaseControl class and controls like buttons and text boxes are made using inheritance.

    If the user clicks clicks the mouse the GUI Manager gets a call to it's MouseDown function. The GuiManager Will then work out which window, if any, the mouse down event was for. It will then make a call to that window's MouseDown function.

    Now the window will use the MouseDown function it inherited from it's parent cBaseWindow. This function works out if any of the window's controls have been pressed. If a control has been pressed a call is made to the controls MouseDown function (the cBase control class has an empty function) so the call is for the derived class.

    Here's where the problem is..

    Some times the program works as intended and the call is made to the MouseDown function of the derived control class, however sometimes this is not the case and the call gets sent to the cBaseControl's MouseDown method.

    screenshot 1
    screenshot 2

    I understood virtual funtions like this:

    The type of the object should be used to determine which function should be called incase inherited classes overide that function. Otherwise, the type of the pointer will always be used.

    A window has a vector of cBaseControl pointers. When a window is created all the controls are added to the vector. This is done by creating objects of derived control classes with "new" and then using push_back to add to the vector.

    The strangest thing is that the problem is intermittant. I can compile the .exe and run it a few times and get different results, sometimes I find that the base method gets called and sometimes i find the dervived class's method is used.

    I need some help with this, I am so confused, I have been programming for about a year, and am hoping that this is some kind of newbie problem that can be fixed relatively easily. I have uploaded my project to make things clearer, I would really appriciate any help or feedback.

    GUITEST.zip

    Try running the exe and clicking a text box field, it might work, it might not, then run it a few more times, and I sure that eventually it will make the wrong call..

    Another stange thing is that the top text box of this window always seems too work.. 0_o

    Anyhow, please help me, thanks for reading this if you go this far

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Perhaps you would want to create a smaller example?

    Code:
    #include <iostream>
    
    using namespace std;
    
    class a 
    {
    public:
        virtual void hi() { cout << "Hi from A" << endl; };
        void hello()  { cout << "Hello from A" << endl; };
    };
    
    class b : public a 
    {
        virtual void hi() { cout << "Hi from B" << endl; };
        void hello()  { cout << "Hello from B" << endl; };
    }
    
    int main()
    {
       a *pa;
    
       pa = new B;
    
       pa->hi();
       pa->hello();
    
       return 0;
    }
    --
    Mats
    Last edited by matsp; 12-07-2007 at 10:48 AM. Reason: Fix missing "void" in class b hi functon.
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Jan 2007
    Posts
    54
    Sorry it's a bit lengthy, I tried to make it as small as possible.. I am not really sure how to cut it down as I am worried that the problem has something to do with something else in the implementation. It's strange because the problem seems to occur randomly, sometimes i click a control and it works, other times it doesn't..

    Thanks for your example, I will run it and check it against what I have..

  4. #4
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    This is very dodgy and wrong:
    Code:
    cWindow1::~cWindow1()
    {
        
    	this->~cBaseWindow();    
    }
    The base class part of the object is already automatically destructed. This function should be removed altogether. The cBaseWindow and cBaseControl destructors should be virtual.

    I find it extremely puzzling that you have reimplemented median-of-three quicksort instead of using the vastly superrior C++ library sort function that already exists. Seriously, just use std::sort!

    cGUIManager::killMe should set _instance to NULL.

    It looks like you would also bennefit from using boost's ptr_containers.
    Last edited by iMalc; 12-07-2007 at 03:02 PM.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  5. #5
    Registered User
    Join Date
    Jan 2007
    Posts
    54
    Thanks for those corrections iMalc, I have made the changes already.

    Have you any idea's about what it is that is causing the overall problem though?

    I really can't figure out why sometimes I run the program, click a textbox, and the right call is made, yet sometimes the wrong call is made..

    I mean surely it should consitently do one or the other. ??

    It can't be random..

  6. #6
    Registered User
    Join Date
    Jan 2007
    Posts
    54
    Is the whole problem happening because the pointers to the derived controls are stored and accessed using a std::vector ?

  7. #7
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by e66n06 View Post
    Is the whole problem happening because the pointers to the derived controls are stored and accessed using a std::vector ?
    No, that should be fine as long as the necessary methods are virtual. It's only bad to treat arrays polymorphically in the sense that if you're storing the objects themselves in the vector. But since you're storing just the pointers, there wont be any slicing involved.

    I would have thought someone else would have responded by now. I'll take another look for you though.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  8. #8
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    I don't know exactly what is causing the problem, but the way most people solve problems in others code is to fix the obvious bugs then see if the problem still happens. More often than not, the bug disappears simply through the act of fixing the obvious bugs. Debugging known-incorrect code is also neither fun nor very productive.

    You have some functions in BaseWindow that are mistakenly not declared as virtual such as MouseTest, Update. Render is correctly virtual, but you've got an incorrect comment saying it shouldn't be. Some of these may well cause something like the problem you are seeing.

    The cWindowLayer class destructor also needs to be virtual, and the current code in the destructor should be deleted.

    You should learn about const-correctness as soon as you can too.

    I'd like to see your updated code before I comment any furthur.
    Last edited by iMalc; 12-11-2007 at 01:14 AM.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  9. #9
    Registered User
    Join Date
    Jan 2007
    Posts
    54
    I have made the changes you said and uploaded the updated version..

    I didn't make all the functions virtual (like MouseTest, Update and Render) because the base function is always used, even in the derived classes, they are never overridden..

    I am still really stuck with this, I don't know what's causing it..

    The only think I have noticed that is consistent is that the top text box (the new file name one) always works, it is held in the third position in the vector..

  10. #10
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by e66n06 View Post
    I didn't make all the functions virtual (like MouseTest, Update and Render) because the base function is always used, even in the derived classes, they are never overridden..
    Oh, I thought I saw that they were overridden, but maybe I was confused between functions of other classes that are not part of the same heirarchy.

    At the moment the zip file linked to is corrupted, and I've already deleted the previous copies.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  11. #11
    Registered User
    Join Date
    Jan 2007
    Posts
    54
    I just uploaded the zip again, it should be ok..

    Thank you for taking an interest in my problem

  12. #12
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    I might have just noticed your problem.
    cPictureBox doesn't override MouseDown, and it will therefore be handled by cBaseControl, giving you your debug message. Neither does cCaption, so that will too.

    You really need to get rid of that custom QuickSort. You use std::sort like this:
    Code:
    std::sort(_windows.begin(), _windows.end(), CompareZ);
    Then you just simplify CompareZ to this:
    Code:
    bool CompareZ(cBaseWindow* l, cBaseWindow* r )
    {
        return l->getZ() < r->getZ();
    }
    That's all there is to it and suddenly you remove a massive amount of inferrior and unnecessary custom sorting code.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  13. #13
    Registered User
    Join Date
    Jan 2007
    Posts
    54
    Cool thanks for that, I have now got rid of the old sort mechanism and uploaded a newer version..

    Though as for the problem, I am still very lost..

    cPictureBox and cCaption do not override the MouseDown event because the they don't have a mouse event. When one of them becomes clicked it is sufficient to use the empty base method.

    However I have changed it so the size of a caption is 0 wide and 0 tall so that now when it tests to see if a caption has been clicked it decides it has not, so does not even call the base method.

    Do you think the pointer's are getting messed up when they get put into the vector? Perhaps somehow they get converted to pointers of the base type if the vector needs to be reallocated..

    I tried allocating space for the vector and it seem to reduce the likely hood of the wrong call being made when a textbox or button was click, though it didn't get rid of the problem, sometimes the wrong call was made..

    I'm so confused about this, help is really appriciated

    Thanks so far iMalc

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 10-28-2009, 09:25 AM
  2. What is a virtual function pointer?
    By ting in forum C++ Programming
    Replies: 4
    Last Post: 03-05-2008, 02:36 AM
  3. virtual function
    By George2 in forum C++ Programming
    Replies: 2
    Last Post: 02-11-2008, 12:51 AM
  4. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  5. structure vs class
    By sana in forum C++ Programming
    Replies: 13
    Last Post: 12-02-2002, 07:18 AM