V
Victor Bazarov
Schüle Daniel said: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::name << 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::basic_string<char,
std::char_traits<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_traits<char>, std::allocator<char> >)
main.cpp: In constructor `YY::YY(std::basic_string<char,
std::char_traits<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_traits<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_traits<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