Thread: Base Class Overloaded Virtual Function

  1. #1
    Registered User
    Join Date
    Apr 2004
    Location
    Ohio
    Posts
    147

    [solved] Base Class Overloaded Virtual Function

    Hello again.

    I've been working with a somewhat complex class heirarchy and have run into a problem. More than likely it stems from not fully understanding how C++ derived classes inherit from base classes.

    To keep things simple, I have the following three classes defined as such:

    Code:
    class Foo
    {
        private:
            virtual void myFunc() { printf("Hello!"); }
            virtual void myFunc2() { printf("'ello!"); }
    };
    
    class Bar : public Foo
    {
        private:
            void myFunc() { printf("Hello 2!"); }
            void myFunc2() { printf("'ello 2!"); }
    };
    
    class FooBar : public Bar
    {
        private:
            void myFunc() { printf("Hello 3!"); }
            void myFunc2() { printf("'ello 3!"); }
    };
    The weird thing that's happening is that when I call the overloaded function from FooBar myFunc() from a list of Foo's (e.g., std::vector<Foo*>), the correct function is called. But myFunc2() calls the function from Foo, not from Bar or FooBar.

    I'm not sure this is clear enough but I'm hoping I provided enough information and that my problem is something really simple or that I just overlooked something.

    Thanks!
    Last edited by leeor_net; 07-12-2009 at 03:38 PM. Reason: Problem solved.

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I see no problem with this except for a few minor things:
    - It's clearer if you add virtual to every function that is virtual. Every function that overrides a virtual function is a base class is considered a virtual function, but it isn't obvious right away unless you can see the base class.
    - Don't use printf, use cout.

    Aside from that, could you provide the smallest simplest code that demonstrates the problem?
    Last edited by Elysia; 07-12-2009 at 02:39 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,793
    They are all private, how are they getting called?

    >>Don't use print, use cout.

    printf is still valid. Please dont bother giving a lecture about type safety.

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    According to my compiler, neither MyFunc nor MyFunc2 are overloaded; code such as
    Code:
        FooBar object;
        Foo* ptr = &object;
        object.myFunc2();
        ptr->myFunc2();
        object.myFunc();
        ptr->myFunc();
    does not of course work, since all the functions are private, but the first ones both resolve to FooBar::myFunc[2] and the second ones both resolve to Foo::myFunc[2], not FooBar. (Edit: by "first ones" I mean object., and by "second ones" I mean ptr->.)

  5. #5
    Registered User
    Join Date
    Apr 2004
    Location
    Ohio
    Posts
    147
    Don't use print, use cout.
    Yes, I know that. This was a quick and dirty example to illustrate a point.

    The code that I'm having trouble with is big and complex. But I'll strip out the stuff that isn't necessary. Here goes:

    Code:
    class Control
    {
    public:
    	Control();
    	void update();
    
    	addControl(Control *);
    	update();
    private:
    	virtual void draw();
    	virtual void initialize();
    };
    
    
    class Window : public Control
    {
    public:
    	Window();
    	~Window();
    
    private:
    	void draw();
    	void initialize();
    
    	std::string	mTitlebar;
    	int		mTitlebarHeight;
    };
    
    
    class DebugWindow : public Window
    {
    public:
        DebugWindow();
        ~DebugWindow();
    
    private:
    	void initialize();
    };

    In particular the trouble shows up when I run the addControl() function:

    Code:
    void Control::addControl(Control *control)
    {
    	mChildControls.push_back(control);
    	mChildControls.back()->initialize();
    }
    mChildControls.back()->initialize() only ever gets called once and only runs the initialize() function from the class Control, not Window or DebugWindow.

    The update function looks like this:

    Code:
    void Control::update()
    {
    	draw();
    
    	for(unsigned int i = 0; i < mChildControls.size(); i++)
    		mChildControls[i]->update();
    }
    This function tells the Control to draw itself and then to iterate through all of its children and tells them to update themselves which in turn calls their update and so on... Now, this works. The correct draw() function is called.

    I may have just answered my own question as to why so now the question has turned into how. But just in case, I'm still asking...

    mChildControls is defined as a vector<Control*>. There are probably a few things here and there that don't appear to be defined but just note that I've stripped out all of the irrelevant functions/variables/etc.
    Last edited by leeor_net; 07-12-2009 at 02:52 PM.

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Fordy View Post
    >>Don't use print, use cout.
    printf is still valid. Please dont bother giving a lecture about type safety.
    But should be avoided in C++, unless you have a very good reason.
    Sure, go ahead and use printf and other C-family functions, but chances are it will become "C+" code instead of C++ code then.

    Oh and consider that private functions aren't inherited, so it may just be that the functions are hidden instead of overloaded. It didn't occur to me before. Perhaps you want to use protected?
    I am also going to have to rant a little about not removing parameter names.
    Last edited by Elysia; 07-12-2009 at 02:44 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Registered User
    Join Date
    Apr 2004
    Location
    Ohio
    Posts
    147
    I;m not one to complain but can we keep the irrelevant chatter out of this topic? This isn't a debate about coding style, appropriateness of function calls, etc.

    I tried moving around the functions to protected and public but no game. Clearly I've misunderstood something.

    Thank you.
    Last edited by leeor_net; 07-12-2009 at 02:50 PM.

  8. #8
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    I'm not sure I've got the hang of what your problem is. I've modified your code so that it makes sense and whatever:
    Code:
    #include <cstdio>
    #include <string>
    #include <vector>
    
    class Control
    {
    public:
    	void update();
    
    	void addControl(Control *);
    private:
        std::vector<Control *> mChildControls;
    	virtual void draw();
    	virtual void initialize();
    };
    
    void Control::draw() {
        printf("Control::draw\n");
    }
    
    void Control::initialize() {
        printf("Control::initialize\n");
    }
    
    class Window : public Control
    {
    public:
    
    private:
    	void draw();
    	void initialize();
    
    	std::string	mTitlebar;
    	int		mTitlebarHeight;
    };
    
    void Window::draw() {
        printf("Window::draw\n");
    }
    
    void Window::initialize() {
        printf("Window::initialize\n");
    }
    
    
    class DebugWindow : public Window
    {
    public:
    
    private:
    	void initialize();
    };
    
    void DebugWindow::initialize() {
        printf("DebugWindow::initialize\n");
    }
    
    void Control::addControl(Control *control)
    {
    	mChildControls.push_back(control);
    	mChildControls.back()->initialize();
    }
    
    void Control::update()
    {
    	draw();
    
    	for(unsigned int i = 0; i < mChildControls.size(); i++)
    		mChildControls[i]->update();
    }
    
    int main() {
        Window foo;
        DebugWindow bar;
        Control bob;
        bob.addControl(&foo);
        bob.addControl(&bar);
        return 0;
    }
    This prints
    Code:
    Window::initialize
    DebugWindow::initialize
    as you probably want. Can you modify this to show what's going on?

  9. #9
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,793
    Quote Originally Posted by leeor_net View Post
    I;m not one to complain but can we keep the irrelevant chatter out of this topic? This isn't a debate about coding style, appropriateness of function calls, etc.
    I know mate. Some people think that by pointing out pointless things like that they are helping.

    Not wanting to ask an obvious question, but when you pass a control to addControl, you are passing a Window or DebugWindow via a Control pointer and not just a plain old Control object are you?

  10. #10
    Registered User
    Join Date
    Apr 2004
    Location
    Ohio
    Posts
    147
    Nope, was definitely passing in a DebugWindow object.

    Now here's the funny thing. I figured out my problem and I really could slap myself.

    The way I have everything set up, I have what I call a Top Level or Root control. When I created DebugWindow, I... forgot to call addControl() to the root... <sigh>. It never occured to me that that could be the problem.

    I hope I haven't wasted anybody's time. I do appreciate the comments and the suggestions... Thanks again!

  11. #11
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    You aren't "overloading" any functions, you're "overriding" them. Overloading has nothing to do with inheritance.
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  12. #12
    Registered User
    Join Date
    Apr 2004
    Location
    Ohio
    Posts
    147
    Yes, I realize that. Thank you for the vocabulary lesson...
    Last edited by leeor_net; 07-13-2009 at 07:19 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 48
    Last Post: 09-26-2008, 03:45 AM
  2. deriving classes
    By l2u in forum C++ Programming
    Replies: 12
    Last Post: 01-15-2007, 05:01 PM
  3. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM
  4. qt help
    By Unregistered in forum Linux Programming
    Replies: 1
    Last Post: 04-20-2002, 09:51 AM
  5. Exporting Object Hierarchies from a DLL
    By andy668 in forum C++ Programming
    Replies: 0
    Last Post: 10-20-2001, 01:26 PM