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 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
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.
[..] 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
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. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
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
|
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...
|
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
|
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.
|
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?
| |
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
/ \
|
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>
|
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
|
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:
|
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...
|
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,...
| |
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...
|
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...
|
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...
|
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...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
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
| |
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...
| | |