473,666 Members | 2,058 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

diamond inheritance, constr. question

Hello C++ NG,

I encountered a strange behaviour in this code

#include <iostream>
#include <cstdlib>
#include <string>

using std::cout;
using std::endl;

#define virtual_Y
#define virtual_X

class A
{
public:
A(std::string s) { cout << (s+">A") << endl; } // <<<< 1
static std::string name;
};

std::string A::name = "<class A>";

class X : public virtual_X A
{
public:
X(std::string s) : A(s+">X") {}
};

class Y : public virtual_Y A
{
public:
Y(std::string s) : A(s+">Y") {}
};

class XX : public X
{
public:
XX(std::string s) : X(s+">XX") {}
};

class YY : public Y
{
public:
YY(std::string s) : Y(s+">YY") {}
};

class C : public XX, public YY
{
public:
C() : XX("C"), YY("C") {}
};

int main()
{
// are the same
cout << A::name << endl;
cout << C::XX::X::A::na me << endl;
return EXIT_SUCCESS;
}

it compiles and runs fine without virtual inheritance
I do get the following hierarchy

A A
\ /
B C
\ /
D
what is strange, when I change

#define virtual_Y virtual
#define virtual_X virtual

and get this diamond hierarchy

A
/ \
B C
\ /
D

then my compiler (gcc-Version 3.3.1) tells me

mond:/pool/PROG/C++/C++/multiple # g++ -o main main.cpp -Wall -g
main.cpp: In constructor `XX::XX(std::ba sic_string<char ,
std::char_trait s<char>, std::allocator< char> >)':
main.cpp:35: error: no matching function for call to `A::A()'
main.cpp:12: error: candidates are: A::A(const A&)
main.cpp:14: error: A::A(std::basic _string<char,
std::char_trait s<char>, std::allocator< char> >)
main.cpp: In constructor `YY::YY(std::ba sic_string<char ,
std::char_trait s<char>, std::allocator< char> >)':
main.cpp:41: error: no matching function for call to `A::A()'
main.cpp:12: error: candidates are: A::A(const A&)
main.cpp:14: error: A::A(std::basic _string<char,
std::char_trait s<char>, std::allocator< char> >)
main.cpp: In constructor `C::C()':
main.cpp:47: error: no matching function for call to `A::A()'
main.cpp:12: error: candidates are: A::A(const A&)
main.cpp:14: error: A::A(std::basic _string<char,
std::char_trait s<char>, std::allocator< char> >)

the bottom line is, it cannot find the approproite constructor
when I provide a default costructor then it compiles
A(std::string s="") { cout << (s+">A") << endl; } // <<<< 1

what is going on here?

Regards, Daniel

Jan 13 '06 #1
4 2053
Schüle Daniel wrote:
I encountered a strange behaviour in this code

#include <iostream>
#include <cstdlib>
#include <string>

using std::cout;
using std::endl;

#define virtual_Y
#define virtual_X

class A
{
public:
A(std::string s) { cout << (s+">A") << endl; } // <<<< 1
static std::string name;
};

std::string A::name = "<class A>";

class X : public virtual_X A
{
public:
X(std::string s) : A(s+">X") {}
};

class Y : public virtual_Y A
{
public:
Y(std::string s) : A(s+">Y") {}
};

class XX : public X
{
public:
XX(std::string s) : X(s+">XX") {}
};

class YY : public Y
{
public:
YY(std::string s) : Y(s+">YY") {}
};

class C : public XX, public YY
{
public:
C() : XX("C"), YY("C") {}
};

int main()
{
// are the same
cout << A::name << endl;
cout << C::XX::X::A::na me << endl;
return EXIT_SUCCESS;
}

it compiles and runs fine without virtual inheritance
I do get the following hierarchy

A A
\ /
B C
\ /
D
Actually, I believe it's

A A
\ /
X Y
\ /
XX YY
\ /
C

what is strange, when I change

#define virtual_Y virtual
#define virtual_X virtual

and get this diamond hierarchy

A
/ \
B C
\ /
D
No, I believe you get

A
/ \
X Y
| |
XX YY
\ /
C

then my compiler (gcc-Version 3.3.1) tells me

mond:/pool/PROG/C++/C++/multiple # g++ -o main main.cpp -Wall -g
main.cpp: In constructor `XX::XX(std::ba sic_string<char ,
std::char_trait s<char>, std::allocator< char> >)':
main.cpp:35: error: no matching function for call to `A::A()'
main.cpp:12: error: candidates are: A::A(const A&)
main.cpp:14: error: A::A(std::basic _string<char,
std::char_trait s<char>, std::allocator< char> >)
main.cpp: In constructor `YY::YY(std::ba sic_string<char ,
std::char_trait s<char>, std::allocator< char> >)':
main.cpp:41: error: no matching function for call to `A::A()'
main.cpp:12: error: candidates are: A::A(const A&)
main.cpp:14: error: A::A(std::basic _string<char,
std::char_trait s<char>, std::allocator< char> >)
main.cpp: In constructor `C::C()':
main.cpp:47: error: no matching function for call to `A::A()'
main.cpp:12: error: candidates are: A::A(const A&)
main.cpp:14: error: A::A(std::basic _string<char,
std::char_trait s<char>, std::allocator< char> >)

the bottom line is, it cannot find the approproite constructor
when I provide a default costructor then it compiles
A(std::string s="") { cout << (s+">A") << endl; } // <<<< 1

what is going on here?


Virtual base class subobjects are initialised by the most derived class'
constructor. If you do not _explicitly_ specify its initialisation in
the most derived class' c-tor's initialiser list, the default c-tor of
the virtual base class is used. If there is no default c-tor, the program
is ill-formed.

You've encountered this specific rule. You either need to provide the
default c-tor in 'A' when 'A' is virtually inherited, or you need to add
the initialiser for it in 'C':

class C : public XX, public YY
{
public:
C() : A("C"), XX("C"), YY("C") {}
};

V
Jan 13 '06 #2
Schüle Daniel wrote:
Hello C++ NG, [snip]
A
/ \
B C
\ /
D

then my compiler (gcc-Version 3.3.1) tells me

mond:/pool/PROG/C++/C++/multiple # g++ -o main main.cpp -Wall -g
main.cpp: In constructor `XX::XX(std::ba sic_string<char ,
std::char_trait s<char>, std::allocator< char> >)':
main.cpp:35: error: no matching function for call to `A::A()'
main.cpp:12: error: candidates are: A::A(const A&)
main.cpp:14: error: A::A(std::basic _string<char,
std::char_trait s<char>, std::allocator< char> >)
main.cpp: In constructor `YY::YY(std::ba sic_string<char ,
std::char_trait s<char>, std::allocator< char> >)':
main.cpp:41: error: no matching function for call to `A::A()'
main.cpp:12: error: candidates are: A::A(const A&)
main.cpp:14: error: A::A(std::basic _string<char,
std::char_trait s<char>, std::allocator< char> >)
main.cpp: In constructor `C::C()':
main.cpp:47: error: no matching function for call to `A::A()'
main.cpp:12: error: candidates are: A::A(const A&)
main.cpp:14: error: A::A(std::basic _string<char,
std::char_trait s<char>, std::allocator< char> >)

the bottom line is, it cannot find the approproite constructor
when I provide a default costructor then it compiles
A(std::string s="") { cout << (s+">A") << endl; } // <<<< 1

what is going on here?

Regards, Daniel


Virtual base must be initialized separetly in all derived classes,
this is the price one must pay for it.
Consider the diamond above and what you have implemented yourself:

B::B(std::strin g s) : A(s+">B") {}
C::C(std::strin g s) : A(s+">C") {}

In the constructor of D how should A be initialized, via B or via C?
Remember: A can be constructed only once
and the compiler can't make the choice, thus you'll need to tell him.
D::D(std::strin g s): A("D"), B("D"), C("D") {}

Regards, Stephan
br****@osb-systems.com
Open source rating and billing engine for communication networks.

Jan 13 '06 #3
[..]
Virtual base must be initialized separetly in all derived classes,
this is the price one must pay for it.
Consider the diamond above and what you have implemented yourself:

B::B(std::strin g s) : A(s+">B") {}
C::C(std::strin g s) : A(s+">C") {}

In the constructor of D how should A be initialized, via B or via C?
Remember: A can be constructed only once
and the compiler can't make the choice, thus you'll need to tell him.
D::D(std::strin g s): A("D"), B("D"), C("D") {}


yes, this makes sense

so the rule would be ..
either the class which merges two branches of diamond together
should call the virtual base constructor explicitly or virtual
base class should have default constructor

Regards, Daniel

Jan 13 '06 #4
Schüle Daniel wrote:
yes, this makes sense

so the rule would be ..
either the class which merges two branches of diamond together
should call the virtual base constructor explicitly or virtual
base class should have default constructor


No, virtual base classes must be initialized in ALL derived classes.
Somebody might provide a rationale for this rule. With
A
/ \
B C
\ / \
D CC
|
E

E must initialize A in its constructors:
class E : public class D {
public:
// E() {}
// ^ errror: no default constructor for A
E() : A("E") {}
};
and similar for class CC.

Regards, Stephan
br****@osb-systems.com
Open source rating and billing engine for communication networks.

Jan 14 '06 #5

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

Similar topics

13
3280
by: John Perks and Sarah Mount | last post by:
Trying to create the "lopsided diamond" inheritance below: >>> class B(object):pass >>> class D1(B):pass >>> class D2(D1):pass >>> class D(D1, D2):pass Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: Error when calling the metaclass bases Cannot create a consistent method resolution
4
1428
by: Steven T. Hatton | last post by:
Below is some code I wrote to get a better understanding of the dynamic verses static type resolution. My intention was to see if there was a way to use references for the static access to the subobjects of an object of derived type. I thought I had seen a way to use references to statically access member functions in a way syntactically similar to how pointers dynamically access the same objects member functions. The overall objective...
5
2472
by: Tony Johansson | last post by:
Hello Experts! It it correct to say that a solution to the diamond problem is to use virtual inheritance with virtual base classes. //Tony
3
2496
by: Tony Johansson | last post by:
Hello Experts!! Assume you have the following diamond inheritance structure. Assume the following at the top you have the Ancestor class and below this class at the same level we have class Child1 and Child2. Class Descendatnt is derived class Child1 and Child2. Assume also that in the top class we have one datamember called number and one method called getNumber(). If you don't use virtual inheritance you will get compile error.
4
2749
by: Alex Hunsley | last post by:
I've seen a few discussion about the use of 'super' in Python, including the opinion that 'super' should only be used to solve inheritance diamond problem. (And that a constructor that wants to call the superclass methods should just call them by name and forget about super.) What is people's opinion on this? Does it make any sense?
2
2413
by: emma middlebrook | last post by:
Hi I come from a C++ background and so am familiar with the 'dreaded inheritance diamond' i.e. the ambiguity of which data to use when a class appears twice in the hierarchy. Here's a link for anyone not familiar: http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.8 .. Base / \
4
2453
by: Pallav singh | last post by:
I am Facing Problem while creating object of Diamond Ring problem solving using Template Kindly let me known where i am committing ERROR Thanks Pallav #include<iostream.h> #include<string.h>
9
10963
by: weird0 | last post by:
How does C++ and C# solve the Diamond problem? With the help of interfaces that is. Can anyone elaborate ....... Regards
6
5720
by: Rocketmagnet | last post by:
Hi all, I have been kind of forced (honestly) into writing a class structure which contains a Diamond of Death, and I'm not entirely sure what to do about it. This is a simplified version of my class structure: class entity { public:
0
8444
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 usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8356
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8869
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. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8639
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 choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7386
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
4198
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4368
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2771
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
2
1775
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 effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.