Who's being dumb here--me, or everyone else? (obscure C++ question)

Discussion in 'Game Development (Technical)' started by Larry Hastings, Aug 17, 2006.

  1. Larry Hastings

    Original Member

    Joined:
    Jul 27, 2004
    Messages:
    213
    Likes Received:
    0
    Specifically, a C++ overloaded-function-namespace-matching question.

    If I compile the following program, with either Visual C++ or G++:
    Code:
    #include <stdio.h>
    class handle { public: int x; }; // compressed to save vertical space
    
    class A
    	{
    	public:
    	void foo(handle *x, char *y, int z = 0);
    	virtual void foo(handle *x) = 0;
    	};
    
    class B : public A
    	{
    	public:
    	virtual void foo(handle *x);
    	};
    
    int main(int argc, char *argv[])
    	{
    	B variable;
    	handle *h = NULL;
    
    	// this works
    	A *pointer = (A *)&variable;
    	pointer->foo(h, "name");
    
    	// this fails
    	variable.foo(h, "name");
    
    	return 0;
    	}
    the compiler will complain about the line reading variable.foo(h, "name");. Why? Because, you fool, the function foo() only takes one parameter! Even a blind man could see it.

    Surely, I reason, the compiler can up-cast B to A and call the non-virtual A::foo() that takes three parameters? Well, I guess it could, but it won't.

    Note that if you change the name of the non-virtual A::foo() and call that, the compiler up-casts it just fine.

    Peeved,
     
  2. TheMysteriousStranger

    Original Member

    Joined:
    Jan 17, 2006
    Messages:
    222
    Likes Received:
    0
    Sounds like it's a compiler related issue, but the real question is: Do you really need to be able to upcast to a same-name overloaded function?

    If yes, then why not simply make one version of the function with three variables, but make the second two variables have default values?

    Or is this just one of those little things that is nagging on your mind for no good reason at all?

    Have you tried making the three-parm version of foo() virtual as well to see if that works?
     
  3. mahlzeit

    Original Member

    Joined:
    Sep 26, 2004
    Messages:
    852
    Likes Received:
    0
    If you want this to work, you need to put
    Code:
    void foo(handle *x, char *y, int z = 0);
    in class B as well. That's just how C++ does overloading. Not a compiler issue, but a language issue. Complain to Bjarne. ;)
     
  4. ggambett

    Moderator Original Member Indie Author

    Joined:
    Jul 26, 2004
    Messages:
    1,982
    Likes Received:
    6
    Yep. If you override one of the overloads, you have to override all of them. Just call the parent's implementation. Yes, it's boring, but at least it's a problem you fix with 3 lines of code per overload.
     
  5. Larry Hastings

    Original Member

    Joined:
    Jul 27, 2004
    Messages:
    213
    Likes Received:
    0
    Aha! I found a way to goad the compiler into doing what I want:
    Code:
    variable.A::foo(h, "name");
    That compiles, and (if you implement both foo()s) runs and behaves the way I wanted.
     
  6. Rainer Deyke

    Indie Author

    Joined:
    Jul 28, 2004
    Messages:
    380
    Likes Received:
    0
    I think this should also work:
    Code:
    class B {
      //...
      using A::foo(handle *x, char *y, int z);
    };
     
  7. Larry Hastings

    Original Member

    Joined:
    Jul 27, 2004
    Messages:
    213
    Likes Received:
    0
    That, in and of itself, failed, as it said "A is not a class or namespace". I added "void", so it said using void A::foo(handle *x, char *y, int z), and MSVS 6 threw an "INTERNAL COMPILER ERROR". I tried it with GCC and it doesn't work either way.

    If you can suggest something that actually works and doesn't require the A:: in front of every call, I'd love to see it.
     
  8. jessechounard

    Original Member

    Joined:
    Apr 4, 2006
    Messages:
    70
    Likes Received:
    0
    Code:
    class B : public A
    {
        void foo(handle *x);
    
        void foo(handle *x, char *y, int z)
        {
            A::foo(x,y,z);
        }
    };
    
     
  9. Dominique Biesmans

    Indie Author

    Joined:
    Jul 27, 2004
    Messages:
    101
    Likes Received:
    0
    This C++ obscurity is called the hiding rule.

    The correct syntax of the 'using' statement would be :

    Code:
    class B {
      //...
      using A::foo;
    };
    (I'm not sure if gcc or msvc6 supports this)
     
  10. Rainer Deyke

    Indie Author

    Joined:
    Jul 28, 2004
    Messages:
    380
    Likes Received:
    0
    If you're using Visual C++ 6.0, forget it. That compiler is so completely broken that no amount of workarounds will get it to compile non-trivial C++ code. Recent versions of gcc, however, should be able to handle most legal C++. (And, yes, the correct syntax is just "using A::foo;".)
     

Share This Page

  • About Indie Gamer

    When the original Dexterity Forums closed in 2004, Indie Gamer was born and a diverse community has grown out of a passion for creating great games. Here you will find over 10 years of in-depth discussion on game design, the business of game development, and marketing/sales. Indie Gamer also provides a friendly place to meet up with other Developers, Artists, Composers and Writers.
  • Buy us a beer!

    Indie Gamer is delicately held together by a single poor bastard who thankfully gets help from various community volunteers. If you frequent this site or have found value in something you've learned here, help keep the site running by donating a few dollars (for beer of course)!

    Sure, I'll Buy You a Beer