Thread: Multiple inheritance issue

  1. #1
    Registered User
    Join Date
    Jul 2003
    Posts
    32

    Multiple inheritance issue

    Hello all,

    I have the following problem when trying to disambiguate the behaviour of a function in the most-derived class:

    Code:
    class B
    {
    public:
        virtual void f() {}
    };
    
    class C : public B
    {
    };
    
    class D : public C, public B
    {
    public:
        virtual void f() {C::B::f();} // error: cannot call member function ‘virtual void B::f()’ without object
    };
    I am using:
    g++ (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu3)


    Thanks!!

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    It's the same as this:
    Code:
    class A
    {
        public:
          void func();
    };
    
    int main()
    {
        A::func();
    }
    You haven't got an object of type A, so you can't call func.

    However, even if you have an object, you are still not going to know which B::f() to call.

    Why do you want to inherit the same class TWICE, and then call the inner base-class via the first class. Perhaps you actually want to do this:
    Code:
    class B
    {
    public:
        virtual void f() {}
    };
    
    class C : public B
    {
    };
    
    class D : public C, public B
    {
    public:
      virtual void f() {
        this->C::f();
      } // error: cannot call member function ‘virtual void B::f()’ without object
    };
    Now, the compiler complains that B is not going to be accessible in D, due to ambiguity. And I agree with that. I've got no idea what you are trying to achieve - almost all cases of inheriting the same class more than once in a derived class is caused by "bad thinking".

    --
    Mats
    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
    Jul 2003
    Posts
    32
    Quote Originally Posted by matsp View Post
    It's the same as this:
    However, even if you have an object, you are still not going to know which B::f() to call.
    It's not the same, because i'm calling f() from a nonstatic function so I *have* and object.
    And, the compiler should know which B::f() to call specifically because I wrote C::B::f(). So it should call the f() of the B in C.

    What i'm trying to achieve is logical, and the code too seems logical to me.

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I'll take your word for that.

    How about this:
    Code:
    class B
    {
    public:
        virtual void f() {}
    };
    
    class C : public B
    {
    public:
      virtual void f()
      {
        this->B::f();
      }
    };
    
    class D : public C, public B
    {
    public:
      virtual void f() {
        this->C::f();
      } 
    };
    --
    Mats
    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.

  5. #5
    Registered User
    Join Date
    Jul 2003
    Posts
    32
    Quote Originally Posted by matsp View Post
    How about this:
    Hmm, I see that in my original example writing C::f() instead of C::B::f() works, and the effect is the same.

    But how do I invoke D::B::f() ? Now I want to call the implementation of f() in the B that is the direct superclass of D.
    Reposting the problematic code.

    Code:
    class B
    {
    public:
        virtual void f() {}
    };
    
    class C : public B
    {
    };
    
    class D : public C, public B
    {
    public:
        virtual void f() {B::f();} // error: cannot call member function ‘virtual void B::f()’ without object
    };
    thanks
    Last edited by Helix; 03-31-2009 at 05:49 AM.

  6. #6
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    The call D::B::f(), no matter how you specify it, is ambiguous unless B is a virtual base. So the call is not possible.

    Your design may be clear in your mind, but that's not the same as saying it is a good design.

    Try giving a hint about what you're trying to do; someone may then be able to provide an alternative that can actually be implemented realistically in C++.

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    And beside from being able to implement it, maybe it will also be possible to maintain and modify later on without having a nightmare of knowing which f() is being called when and where.

    --
    Mats
    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.

  8. #8
    Registered User
    Join Date
    Jul 2003
    Posts
    32
    Quote Originally Posted by grumpy View Post
    The call D::B::f(), no matter how you specify it, is ambiguous unless B is a virtual base. So the call is not possible.
    Grumpy, i worked a little to produce this minimalistic example, so to keep things simple. one thing I know for sure, is that I don't want B to be a virtual base class.

    I'm not convinced that this call shouldn't be possible. It says in the Standard (10.2.5) that for nonvirtual base classes one uses explicit qualification (an inheritance path) to specify which sub-object is meant. I've seen this exemplified with fields, but it should work with functions.

    Furthermore: I was not *very* suprised to see that Visual Studio compiles and calls the implementation of f() that I would expect! If you wanna try it:

    Code:
    class B
    {
    public:
        char mC;
        B(char c) : mC(c) {}
        virtual char f() {return mC;}
    };
    
    class C : public B
    {
    public:
        C() : B('C') {}
        virtual char f() {return 'A';}
    };
    
    class D : public C, public B
    {
    public:
        D() : C(), B('D') {}
        virtual char f() {return B::f();} // error: cannot call member function ‘virtual void B::f()’ without object
    };
    Code:
    void main() {    std::cout<<D().f();
    }

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Visual Studio is NOT a good measure of "standards comliance". gcc makes much more of an effort to comply with standards and being correct.

    --
    Mats
    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.

  10. #10
    Registered User
    Join Date
    Jul 2003
    Posts
    32
    Quote Originally Posted by matsp View Post
    Visual Studio is NOT a good measure of "standards comliance". gcc makes much more of an effort to comply with standards and being correct.

    --
    Mats

    Well I didn't mean that g++ should conform to Visual Studio .
    I was just saying....

  11. #11
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Helix View Post
    Well I didn't mean that g++ should conform to Visual Studio .
    I was just saying....
    I didn't say you said that. I was just pointing out that for good and bad, Visual Studio does things that other compilers MAY or MAY NOT be able to do. Sometimes that's a good thing, sometimes it's not.

    --
    Mats
    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.

  12. #12
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Quote Originally Posted by Helix
    But how do I invoke D::B::f() ?
    Quote Originally Posted by matsp
    Now, the compiler complains that B is not going to be accessible in D, due to ambiguity.
    The compiler is right ...


    I cannot think of a situation where broken triangle inheritance is ever the right solution for anything. Can you give us a few concrete hints about your design?
    Last edited by CornedBee; 03-31-2009 at 11:28 AM.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  13. #13
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Use virtual inheritance like so:
    Code:
    class B
    {
    public:
        virtual void f() {}
    };
    
    class C : public virtual B
    {
    };
    
    class D : public C, public virtual B
    {
    public:
        virtual void f() {B::f();} // error: cannot call member function ‘virtual void B::f()’ without object
    };

  14. #14
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by bithub View Post
    Use virtual inheritance like so:
    Code:
    class B
    {
    public:
        virtual void f() {}
    };
    
    class C : public virtual B
    {
    };
    
    class D : public C, public virtual B
    {
    public:
        virtual void f() {B::f();} // error: cannot call member function ‘virtual void B::f()’ without object
    };
    But that assumes (which I think is where the key point is) that there should only be one B instance within D. If that's not the case, then this solution will not work.

    --
    Mats
    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.

  15. #15
    Registered User
    Join Date
    Jul 2003
    Posts
    32
    Quote Originally Posted by matsp View Post
    But that assumes (which I think is where the key point is) that there should only be one B instance within D. If that's not the case, then this solution will not work.
    I did say I wanted multiple sub-object copies in my design.

    Anyway.
    So the conclusion is, this is not standard behavior, that I am asking for?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 16
    Last Post: 06-08-2009, 03:03 PM
  2. Multiple inheritance in C#
    By DavidP in forum C# Programming
    Replies: 1
    Last Post: 06-27-2008, 04:41 PM
  3. Virtual function and multiple inheritance
    By George2 in forum C++ Programming
    Replies: 68
    Last Post: 02-13-2008, 01:15 AM
  4. Multiple Inheritance - Size of Classes?
    By Zeusbwr in forum C++ Programming
    Replies: 10
    Last Post: 11-26-2004, 09:04 AM
  5. Multiple virtual inheritance
    By kitten in forum C++ Programming
    Replies: 3
    Last Post: 08-10-2001, 10:04 PM

Tags for this Thread