473,566 Members | 2,924 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Virtual inheritance and constructors in base classes with const membervariables

Hi,

I have a question, in a "dreaded diamond" situation, regarding the
following code:

---- Begin code

#include <iostream>

using namespace std;

template <int n>
class Animal
{
protected:
int extremities_;
const int flag_;
public:
Animal(const int &numext) :
extremities_(nu mext), flag_(1)
{cout << numext << " Extrms\n";}
Animal() {cout << "A NoArgs\n";} // Breaks things
// Animal() : flag_(0)
// {cout << "A NoArgs\n";} // Uncomment to fix code
};

template <int n>
class Bird : public virtual Animal<n>
{
public:
Bird() : Animal<n>(2) {cout << "Bird Args\n";}
};

template <int n>
class CrippledHorse : public virtual Animal<n>
{
public:
CrippledHorse(c onst int &numext) :
Animal<n>(numex t) {cout << "CH Args\n";}
CrippledHorse() {cout << "CH NoArgs\n";}
};

template <int n>
class CrippledPegasus :
public virtual CrippledHorse<n >, public virtual Bird<n>
{
public:
CrippledPegasus (const int &numext) :
Animal<n>(numex t) {cout << "CP Args\n";}
};

int main(int argc, char *argv[])
{
CrippledPegasus <0> foo(5);

return 0;
}

---- End code

When I try to compile it with g++ (GCC) 3.4.2 20041017 (Red Hat
3.4.2-6.fc3) I get the following error messages:

tst.cpp: In constructor `Animal<n>::Ani mal() [with int n = 0]':
tst.cpp:33: instantiated from `CrippledHorse< n>::CrippledHor se() [with
int n = 0]'
tst.cpp:42: instantiated from `CrippledPegasu s<n>::CrippledP egasus(const
int&) [with int n = 0]'
tst.cpp:47: instantiated from here
tst.cpp:15: error: uninitialized member `Animal<0>::fla g_' with `const'
type `const int'

The templates are not necessary to reproduce the error, but they help
tracing what's going on: after fiddling with it, I think the problem
comes because, for a reason unknown to me, CrippledHorse calls the
Animal constructor without any arguments, which doesn't initialize the
const member variable producing the compiler error.
If my understanding of virtual inheritance is correct, CrippledPegasus
is the responsible of calling the Animal constructor. Thus, neither
CrippledHorse nor Bird should call any of the Animal constructors. In
particular, CrippledHorse should have no reason to deal with Animal()
(the version with no arguments).
However, CrippledHorse does have something to do with Animal() , as
proven by the fact that initializing as in
Animal() : flag_(0)
{cout << "A NoArgs\n";} // Uncomment to fix code
fixes the problem.
My puzzlement is even higher when, after running the version of the
code that compiles, I see that the line "A NoArgs" never appears in the
output (as it should be since that constructor isn't supposed to be
called anyway).
So, my question is, is this the standard C++ behavior and my ideas are
wrong? Could this be a problem with the way the compiler implements
things? (sorry, I don't have access to a different compiler yet)
I would sleep much better at night if I didn't have to define Animal()
at all, since that hinders readability because it's never supposed to be
called...
Thanks,

Xavier
Jul 23 '05 #1
4 4598
Xavier wrote:
[ code removed ]
The templates are not necessary to reproduce the error, but they help
tracing what's going on: after fiddling with it, I think the problem
comes because, for a reason unknown to me, CrippledHorse calls the
Animal constructor without any arguments, which doesn't initialize the
const member variable producing the compiler error.
If my understanding of virtual inheritance is correct, CrippledPegasus
is the responsible of calling the Animal constructor. Thus, neither
CrippledHorse nor Bird should call any of the Animal constructors. In
particular, CrippledHorse should have no reason to deal with Animal()
(the version with no arguments).
However, CrippledHorse does have something to do with Animal() , as
proven by the fact that initializing as in
Animal() : flag_(0)
{cout << "A NoArgs\n";} // Uncomment to fix code
fixes the problem.
My puzzlement is even higher when, after running the version of the
code that compiles, I see that the line "A NoArgs" never appears in the
output (as it should be since that constructor isn't supposed to be
called anyway).
So, my question is, is this the standard C++ behavior and my ideas are
wrong? Could this be a problem with the way the compiler implements
things? (sorry, I don't have access to a different compiler yet)
I would sleep much better at night if I didn't have to define Animal()
at all, since that hinders readability because it's never supposed to be
called...
Thanks,

Xavier


Hi Xavier,

your problem is not at all related to templates. Consider the following
code:
#include <iostream>

using namespace std;

struct ABC
{
ABC()
{
cout<<"ABC::ABC ()" << endl;
}
};

struct A : virtual public ABC
{
A()
: ABC()
{
cout << "A::A()" << endl;
}
};

struct B : virtual public ABC
{
B()
: ABC()
{
cout << "B::B()" << endl;
}
};
struct C : public A, public B
{
C()
: A()
, B()
{
cout << "C::C()" << endl;
}
};

int main()
{
C c;
return 0;
}
It will print:
ABC::ABC()
A::A()
B::B()
C::C()
The compiler is responsible that the virtual base class gets constructed
exactly once. But this still means that every derived class that
has a virtual base class needs to call the base class' constructor.
Here A and B call ABC's constructor, but it only gets executed once.
C does not call ABC's constructor and it also must not call it, because
it is not derived directly from it.

Hope that helps.
Consider reading ISO/IEC 14882 chapter 10.
Cheers,

Tom
Jul 23 '05 #2
Thomas Maier-Komor wrote:
Consider reading ISO/IEC 14882 chapter 10.


and even more appropriate sections 12.6 and 12.7
Jul 23 '05 #3
On Fri, 29 Apr 2005 11:54:20 +0200, Xavier <dont@like_sp.a m> wrote:
Hi,

I have a question, in a "dreaded diamond" situation, regarding the
following code: [...]
When I try to compile it with g++ (GCC) 3.4.2 20041017 (Red Hat
3.4.2-6.fc3) I get the following error messages:
[...]

Considering that g++ 3.3.2 on OpenBSD 3.6 compiles the example with no
errors and what Stroustrup has to say in section 15.2.4.1:
"For example, the language ensures that a constructor of a
virtual base is called exactly once. The constructor of a
virtual base is invoked (implicitly or explicitly) from the
constructor for the complete object (the constructor for the
most derived class)."
I'd say it's a compiler issue, not a language issue.
However, CrippledHorse does have something to do with Animal() , as
proven by the fact that initializing as in
Animal() : flag_(0)
{cout << "A NoArgs\n";} // Uncomment to fix code
fixes the problem.
My puzzlement is even higher when, after running the version of the
code that compiles, I see that the line "A NoArgs" never appears in the
output (as it should be since that constructor isn't supposed to be
called anyway).
Sounds like the bytecode g++ 3.4.2 emits is correct; the error is
probably just in the overload-resolution components of g++ (or the
components which check that const variables get initialized or
whatever spits out the error).
So, my question is, is this the standard C++ behavior and my ideas are
wrong? Could this be a problem with the way the compiler implements
things? (sorry, I don't have access to a different compiler yet)


You're right. The error from g++ 3.4.2 is non-standard behavior.
Fortunately, you found a workaround.

Kanenas
Jul 23 '05 #4
On Fri, 29 Apr 2005 14:21:58 +0200, Thomas Maier-Komor
<ma******@lpr.n o-spam.e-technik.tu-muenchen.de> wrote:

[...]
your problem is not at all related to templates. Consider the following
code:
As Xavier said:
The templates are not necessary to reproduce the error, but they help
tracing what's going on:


The compiler is responsible that the virtual base class gets constructed
exactly once. But this still means that every derived class that
has a virtual base class needs to call the base class' constructor.
Here A and B call ABC's constructor, but it only gets executed once.
Construction generally consists of allocating space and then invoking
a constructor, so the statement that a virtual base's constructor
needs to be called (or rather, invoked) more than once is a
contradiction. Considering that to invoke a constructor will execute
it, it's contradictory to say that ABC's constructor is called (or
rather, invoked) twice when constructing a C yet is executed exactly
once.
C does not call ABC's constructor and it also must not call it, because
it is not derived directly from it.

A class can (explicity or implicitly) invoke the constructor for a
virtual base class in an initializer list even if not a direct
descendent; indeed, it must.

As you later suggested, I looked at section 12.6 and found:
12.6.2.5:
"Initializa tion shall proceed in the following order:
-- First, and only for the constructor of the most derived class as
described below, virtual base classes shall be initialized in the
order they appear on a depth-first left-to-right traversal of the
directed acyclic graph of base classes, where "left-to-right" is the
order of appearance of the base class names in the derived class
base-specifier-list."

This, too, implies the constructors for A and B will not invoke ABC's
constructor when constructing a C.

Kanenas
Jul 23 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
4220
by: Alexander Stippler | last post by:
I've got an inheritance structure with two coupled "dreaded diamonds" like shown below: A / \ / \ B C \ / \ \ / \ D E \ /
45
6323
by: Ben Blank | last post by:
I'm writing a family of classes which all inherit most of their methods and code (including constructors) from a single base class. When attempting to instance one of the derived classes using parameters, I get CS1501 (no method with X arguments). Here's a simplified example which mimics the circumstances: namespace InheritError { //...
3
3767
by: Marcin Kalicinski | last post by:
Hi, Having the following program: #include <iostream> struct A { A() { std::cout << "A::A()\n"; } A(const A &) { std::cout << "A::A(const A &)\n"; }
12
2645
by: mijobee | last post by:
I'm very new to c++ and just writing some code to learn. I've run into a problem, with a javaish design, and want to know if there is any possible solution without modifying the design. I've read up on virtual inheritance and from my understanding this should work fine but I haven't found any docs that use such a tangled example. The gcc...
5
1972
by: toton | last post by:
Hi, I want a few of my class to overload from a base class, where the base class contains common functionality. This is to avoid repetition of code, and may be reducing amount of code in binary, not to get polymorphic behavior. None of them has virtual methods, and are self contained (no destructor at all) thus do not have a chance to have...
7
2104
by: Markus Svilans | last post by:
Hello, My question involves virtual functions and inheritance. Suppose we have a class structure, that consists of "data" classes, and "processor" classes. The data classes are derived from BufferBase, and customized in order to be able to a type of data (of any kind, such as chunks of audio samples from a sound card). The processor...
7
3396
by: BeautifulMind | last post by:
In case of inheritence the order of execution of constructors is in the order of derivation and order of destructor execution is in reverse order of derivation. Is this case also true in case class is derived as virtual? How does the order of construction/destruction is impacted if the base class is derived as virtual or non virtual? just...
17
3512
by: Jess | last post by:
Hello, If I have a class that has virtual but non-pure declarations, like class A{ virtual void f(); }; Then is A still an abstract class? Do I have to have "virtual void f() = 0;" instead? I think declaring a function as "=0" is the same
0
1300
by: =?Utf-8?B?Zmplcm9uaW1v?= | last post by:
Hi all, As I mentioned in a previous thread (see 'Dbghelp, symbols and templates' in microsoft.public.windbg), we created a powerful symbol engine using dbghelp to dump the contents of the stack symbols when an exception occurs. The engine is able to dereference and process UDT symbols up to their highest base class. It also supports...
0
7673
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7893
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
8109
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7645
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
7953
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
5213
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3626
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2085
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
0
926
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.