Virtual inheritance and multiple files

K

Klaas Vantournhout

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) { }
 
B

BobR

Klaas Vantournhout wrote in message
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.
 
F

Frank

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

Klaas Vantournhout

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

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

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top