Virtual inheritance and multiple files

Discussion in 'C++' started by Klaas Vantournhout, Nov 19, 2006.

  1. Hi,

    Recently I obtained a problem with virtual inheritance when implementing
    it in multiple files. To present the problem I have included at the
    bottom of this post the code of the 4 files. I show results with the
    gnu compiler but i have the same results with the intel compiler.

    file1.cpp compiles without a problem, the problem occurs when compiling
    file2.cpp. It complains about not finding the constructor of the class
    base.

    [klaas@blackdwarf cpptest]$ g++ -c -Wall file2.cpp
    file2.cpp: In constructor 'doublederived::doublederived(int)':
    file2.cpp:3: error: no matching function for call to 'base::base()'
    file1.hpp:3: note: candidates are: base::base(int)
    file1.hpp:1: note: base::base(const base&)

    When derived does not virtual inherit base, this does not give a
    problem. Is there a reason why this is not working?

    Regards
    Klaas

    // file1.hpp
    class base {
    public:
    base(int);
    };

    class derived : public virtual base {
    public:
    derived(int);
    };

    // file1.cpp
    #include <iostream>
    #include "file1.hpp"
    base::base(int a) { std::cout << a << std::endl;}
    derived::derived(int a) : base(a) { }

    // file2.hpp
    #include "file1.hpp"
    class doublederived : public derived {
    public:
    doublederived(int);
    };

    // file2.cpp
    #include "file2.hpp"
    doublederived::doublederived(int a) : derived(a) { }
     
    Klaas Vantournhout, Nov 19, 2006
    #1
    1. Advertising

  2. Klaas Vantournhout

    BobR Guest

    Klaas Vantournhout wrote in message
    <4560e845$0$1120$>...
    >Hi,
    >
    >Recently I obtained a problem with virtual inheritance when implementing
    >it in multiple files. To present the problem I have included at the
    >bottom of this post the code of the 4 files. I show results with the
    >gnu compiler but i have the same results with the intel compiler.
    >
    >file1.cpp compiles without a problem, the problem occurs when compiling
    >file2.cpp. It complains about not finding the constructor of the class
    >base.
    >
    >[klaas@blackdwarf cpptest]$ g++ -c -Wall file2.cpp
    >file2.cpp: In constructor 'doublederived::doublederived(int)':
    >file2.cpp:3: error: no matching function for call to 'base::base()'
    >file1.hpp:3: note: candidates are: base::base(int)
    >file1.hpp:1: note: base::base(const base&)
    >
    >When derived does not virtual inherit base, this does not give a
    >problem. Is there a reason why this is not working?
    >
    >Regards
    >Klaas
    >
    >// file1.hpp
    >class base {
    > public:
    > base(int);
    >};
    >
    >class derived : public virtual base {
    > public:
    > derived(int);
    >};
    >
    >// file1.cpp
    >#include <iostream>
    >#include "file1.hpp"
    >base::base(int a) { std::cout << a << std::endl;}
    >derived::derived(int a) : base(a) { }
    >
    >// file2.hpp
    >#include "file1.hpp"
    >class doublederived : public derived {
    > public:
    > doublederived(int);
    >};
    >
    >// file2.cpp
    >#include "file2.hpp"
    >doublederived::doublederived(int a) : derived(a) { }


    I'm not real sharp on this one. I looked at Eckel's and found this (in
    diamond example):

    class Left : virtual public Top { public: <snip>
    Left(int m, int n) : Top(m) { y = n; }
    };

    class Right : virtual public Top { public: <snip>
    Right(int m, int n) : Top(m) { z = n; }
    };

    class Bottom : public Left, public Right {
    int w;
    public:
    Bottom(int i, int j, int k, int m)
    : Top(i), Left(0, j), Right(0, k) { w = m; }
    };

    Note how, even though Bottom did not directly derive from Top, it was still
    initialised in Bottom.

    So, maybe try(?):

    doublederived::doublederived(int a) : base(a), derived(a) { }

    Makes since to me because your error is in looking for a base default
    constructor, instead of using your defined constructor.

    I'm just guessing at this, but, it shouldn't hurt to try it.
    I tried it (in a single file) and it worked.

    --
    Bob R
    POVrookie
     
    BobR, Nov 20, 2006
    #2
    1. Advertising

  3. Klaas Vantournhout

    Frank Guest

    I think BobR gave the correct solution. In this case, virtual
    inheritance makes the constructor of "base" delay to the most derived
    class "'doublederived" and suppresses the call of it from "derived".
    Actually, in the constructor of " base", if you don't invoke the
    constructor of "base", its default constructor will be the first
    candidate.

    "BobR дµÀ£º
    "
    > Klaas Vantournhout wrote in message
    > <4560e845$0$1120$>...
    > >Hi,
    > >
    > >Recently I obtained a problem with virtual inheritance when implementing
    > >it in multiple files. To present the problem I have included at the
    > >bottom of this post the code of the 4 files. I show results with the
    > >gnu compiler but i have the same results with the intel compiler.
    > >
    > >file1.cpp compiles without a problem, the problem occurs when compiling
    > >file2.cpp. It complains about not finding the constructor of the class
    > >base.
    > >
    > >[klaas@blackdwarf cpptest]$ g++ -c -Wall file2.cpp
    > >file2.cpp: In constructor 'doublederived::doublederived(int)':
    > >file2.cpp:3: error: no matching function for call to 'base::base()'
    > >file1.hpp:3: note: candidates are: base::base(int)
    > >file1.hpp:1: note: base::base(const base&)
    > >
    > >When derived does not virtual inherit base, this does not give a
    > >problem. Is there a reason why this is not working?
    > >
    > >Regards
    > >Klaas
    > >
    > >// file1.hpp
    > >class base {
    > > public:
    > > base(int);
    > >};
    > >
    > >class derived : public virtual base {
    > > public:
    > > derived(int);
    > >};
    > >
    > >// file1.cpp
    > >#include <iostream>
    > >#include "file1.hpp"
    > >base::base(int a) { std::cout << a << std::endl;}
    > >derived::derived(int a) : base(a) { }
    > >
    > >// file2.hpp
    > >#include "file1.hpp"
    > >class doublederived : public derived {
    > > public:
    > > doublederived(int);
    > >};
    > >
    > >// file2.cpp
    > >#include "file2.hpp"
    > >doublederived::doublederived(int a) : derived(a) { }

    >
    > I'm not real sharp on this one. I looked at Eckel's and found this (in
    > diamond example):
    >
    > class Left : virtual public Top { public: <snip>
    > Left(int m, int n) : Top(m) { y = n; }
    > };
    >
    > class Right : virtual public Top { public: <snip>
    > Right(int m, int n) : Top(m) { z = n; }
    > };
    >
    > class Bottom : public Left, public Right {
    > int w;
    > public:
    > Bottom(int i, int j, int k, int m)
    > : Top(i), Left(0, j), Right(0, k) { w = m; }
    > };
    >
    > Note how, even though Bottom did not directly derive from Top, it was still
    > initialised in Bottom.
    >
    > So, maybe try(?):
    >
    > doublederived::doublederived(int a) : base(a), derived(a) { }
    >
    > Makes since to me because your error is in looking for a base default
    > constructor, instead of using your defined constructor.
    >
    > I'm just guessing at this, but, it shouldn't hurt to try it.
    > I tried it (in a single file) and it worked.
    >
    > --
    > Bob R
    > POVrookie
     
    Frank, Nov 20, 2006
    #3
  4. Thanks Bob and Frank, indeed that was it. The most derived class must
    explicitly invoke the virutal base class's constructor.

    Great

    thanks both

    klaas


    Frank wrote:
    > I think BobR gave the correct solution. In this case, virtual
    > inheritance makes the constructor of "base" delay to the most derived
    > class "'doublederived" and suppresses the call of it from "derived".
    > Actually, in the constructor of " base", if you don't invoke the
    > constructor of "base", its default constructor will be the first
    > candidate.
    >
    > "BobR 写é“:
    > "
    >> Klaas Vantournhout wrote in message
    >> <4560e845$0$1120$>...
    >>> Hi,
    >>>
    >>> Recently I obtained a problem with virtual inheritance when implementing
    >>> it in multiple files. To present the problem I have included at the
    >>> bottom of this post the code of the 4 files. I show results with the
    >>> gnu compiler but i have the same results with the intel compiler.
    >>>
    >>> file1.cpp compiles without a problem, the problem occurs when compiling
    >>> file2.cpp. It complains about not finding the constructor of the class
    >>> base.
    >>>
    >>> [klaas@blackdwarf cpptest]$ g++ -c -Wall file2.cpp
    >>> file2.cpp: In constructor 'doublederived::doublederived(int)':
    >>> file2.cpp:3: error: no matching function for call to 'base::base()'
    >>> file1.hpp:3: note: candidates are: base::base(int)
    >>> file1.hpp:1: note: base::base(const base&)
    >>>
    >>> When derived does not virtual inherit base, this does not give a
    >>> problem. Is there a reason why this is not working?
    >>>
    >>> Regards
    >>> Klaas
    >>>
    >>> // file1.hpp
    >>> class base {
    >>> public:
    >>> base(int);
    >>> };
    >>>
    >>> class derived : public virtual base {
    >>> public:
    >>> derived(int);
    >>> };
    >>>
    >>> // file1.cpp
    >>> #include <iostream>
    >>> #include "file1.hpp"
    >>> base::base(int a) { std::cout << a << std::endl;}
    >>> derived::derived(int a) : base(a) { }
    >>>
    >>> // file2.hpp
    >>> #include "file1.hpp"
    >>> class doublederived : public derived {
    >>> public:
    >>> doublederived(int);
    >>> };
    >>>
    >>> // file2.cpp
    >>> #include "file2.hpp"
    >>> doublederived::doublederived(int a) : derived(a) { }

    >> I'm not real sharp on this one. I looked at Eckel's and found this (in
    >> diamond example):
    >>
    >> class Left : virtual public Top { public: <snip>
    >> Left(int m, int n) : Top(m) { y = n; }
    >> };
    >>
    >> class Right : virtual public Top { public: <snip>
    >> Right(int m, int n) : Top(m) { z = n; }
    >> };
    >>
    >> class Bottom : public Left, public Right {
    >> int w;
    >> public:
    >> Bottom(int i, int j, int k, int m)
    >> : Top(i), Left(0, j), Right(0, k) { w = m; }
    >> };
    >>
    >> Note how, even though Bottom did not directly derive from Top, it was still
    >> initialised in Bottom.
    >>
    >> So, maybe try(?):
    >>
    >> doublederived::doublederived(int a) : base(a), derived(a) { }
    >>
    >> Makes since to me because your error is in looking for a base default
    >> constructor, instead of using your defined constructor.
    >>
    >> I'm just guessing at this, but, it shouldn't hurt to try it.
    >> I tried it (in a single file) and it worked.
    >>
    >> --
    >> Bob R
    >> POVrookie

    >
     
    Klaas Vantournhout, Nov 20, 2006
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. qazmlp
    Replies:
    19
    Views:
    798
    Daniel T.
    Feb 4, 2004
  2. cppsks
    Replies:
    0
    Views:
    827
    cppsks
    Oct 27, 2004
  3. Replies:
    4
    Views:
    959
    M.E.Farmer
    Feb 13, 2005
  4. Ashwin
    Replies:
    2
    Views:
    347
    Pierre Barbier de Reuille
    Aug 1, 2006
  5. Rouslan Korneychuk
    Replies:
    8
    Views:
    604
    Rouslan Korneychuk
    Feb 10, 2011
Loading...

Share This Page