Thread: C++ method lookup

  1. #1
    Registered User
    Join Date
    Aug 2005
    Posts
    96

    C++ method lookup

    Umm so I ran into this weird problem today.
    It's probably my own ignorance but I wanted to know why this happens
    and if it's supposed to.

    Say I have this code:
    (Using MinGW/GCC 4.5 compiler on Windows)

    Code:
    class Bar
    {
    protected:
    
        // ctor/dtor
    
        ssize_t Write(const void* buffer, size_t bytes);
    };
    
    class Foo : public Bar
    {
    public:
    
        // ctors etc.
    
        // ...
    
        void Write(int8_t value);
    };
    
    
    void Foo::Write(int8_t value)
    {
        // UH OH
        // Compiler complains that there is no "matching function call to
        // Foo::Write(void*, unsinged int)"
        Write(&value, sizeof(value));
    }
    So what is going on here?

    It appears that the compiler "knows" that there is a Write() method
    that takes two arguments, but for some reason it can't look it up.

    Now if I say:

    Code:
    void Foo::Write(int8_t value)
    {
        Bar::Write(&value, sizeof(value));
    }
    that sort of works until we get to the link stage...

  2. #2
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    make Bar::Write virtual, and it should work

  3. #3
    Registered User
    Join Date
    Aug 2005
    Posts
    96
    Quote Originally Posted by Elkvis View Post
    make Bar::Write virtual, and it should work
    Mind explaining why?
    Because that doesn't make sense to me and when I tried it it didn't work.
    Thanks for the reply though.

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by sethjackson
    So what is going on here?

    It appears that the compiler "knows" that there is a Write() method
    that takes two arguments, but for some reason it can't look it up.
    There is a name hiding mechanism that applies to derived classes. Basically, when you introduce a member name in a derived class that is the same as that of a member in the base class, the base class name is hidden. Thus, the attempt to overload the Write member function in Foo results in the Bar::Write being hidden. One solution is to use a using declaration:
    Code:
    class Foo : public Bar
    {
    public:
    
        // ctors etc.
    
        // ...
    
        void Write(int8_t value);
    protected:
        using Bar::Write;
    };
    In this case, another option is to qualify the name, since it is implementation detail anyway:
    Code:
    void Foo::Write(int8_t value)
    {
        // UH OH
        // Compiler complains that there is no "matching function call to
        // Foo::Write(void*, unsinged int)"
        Bar::Write(&value, sizeof(value));
    }
    EDIT:
    I noticed that you discovered the second method for yourself, but then leave a cliffhanger about "that sort of works until we get to the link stage". There should not be a linker problem unless you forgot to implement Bar::Write.
    Last edited by laserlight; 11-25-2010 at 12:44 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Aug 2005
    Posts
    96
    Aha! Thanks laserlight. I've got it working now.
    Yeah I don't know why I was getting unresolved symbols.
    I probably did something dumb with my build.

    Thanks for the help.

  6. #6
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    I would also argue that this is a poor design. Changing the declaration of Write in a derived class makes the hierarchy difficult to understand and I don't recommend doing this. There is a much better way using interfaces and then allowing derived classes to implement the interface the way they need to but every derived object must adhere to the interface. This means that while Write() may write differently in derived classes it follows the same declaration and prototype in the interface.

    I could also argue that if Foo needed a different Write() then perhaps a separate function should be provided in Bar for this very reason. However I'm not a big fan of overloaded functions because they can cause confusion when taken to the extreme. I prefer two separate functions with two distinct names. Note I said when taken to the extreme. In certain circumstances overloaded functions are fine. But again if you are programming to an interface instead of an implementation a lot of this confusion can be easily avoided.

  7. #7
    Registered User
    Join Date
    Aug 2005
    Posts
    96
    EDIT:

    Point taken. Thanks.
    I'm gonna refactor this.
    Thanks for the help everyone.
    Last edited by sethjackson; 11-25-2010 at 10:11 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Packet Container Class
    By ChaoticXSinZ in forum C++ Programming
    Replies: 2
    Last Post: 11-01-2010, 12:07 AM
  2. on method pointers and inheritance
    By BrownB in forum C++ Programming
    Replies: 2
    Last Post: 03-02-2009, 07:50 PM
  3. Best communication method to thousand childs?
    By Ironic in forum C Programming
    Replies: 8
    Last Post: 11-08-2008, 12:30 AM
  4. Overriding a method in C
    By DavidDobson in forum C Programming
    Replies: 1
    Last Post: 07-05-2008, 07:51 AM
  5. Replies: 2
    Last Post: 01-22-2008, 04:22 PM