Re: Virtual Base Class, "Diamond" Inheritance
On Dec 1, 2:05 pm, Ryan Clark <RyanCl...@alum.berkeley.edu> wrote:
Hello,
I'm getting a little frustrated with constructor syntax when I use
virtual base classes.
Take the following code (classic diamond inheritance):
class BaseClass
{
int base_value;
public:
BaseClass(int bv) : base_value(0)
{
base_value = bv;
}
virtual ~BaseClass()
{
}
int value() const
{
return base_value;
}
};
class A : public virtual BaseClass
{
public:
A() : BaseClass(1)
{
}
virtual ~A()
{
}
};
class B : public virtual BaseClass
{
public:
B() : BaseClass(2)
{
}
virtual ~B()
{
}
};
class Diamond: public A, public B
{
public:
Diamond(): BaseClass(3)
{
}
virtual ~Diamond()
{
}
};
int main(int argc, char* argv[])
{
Diamond d;
printf("Hello World! %d\n", d.value());
return 0;
}
This code won't compile without the calls to the BaseClass constructor
in A and B, even though they are never called. Why is that? I have
already told the compiler, "this class will be instantiated somewhere
else" (right?), why do I have to add completely meaningless code to
make the compiler happy?
What's more... if add this class:
class Diamond2 : public Diamond
{
public:
Diamond2(): BaseClass(4)
{
#include <iostream>
class BaseClass
{
int base_value;
public:
BaseClass(int bv = 0) : base_value(bv)
{
}
virtual ~BaseClass() { }
int value() const { return base_value; }
};
class A : public virtual BaseClass
{
public:
A() { }
~A() { }
};
class B : public virtual BaseClass
{
public:
B() { }
~B() { }
};
class Diamond: public A, public B
{
public:
Diamond(): BaseClass(3) { }
~Diamond() { }
};
int main(int argc, char* argv[])
{
Diamond d;
std::cout << "d.value() is ";
std::cout << d.value() << std::endl;
}
}
virtual ~Diamond2()
{
}
};
And change variable d to type Diamond2, it won't compile without the
constructor call to BaseClass. It seems to me that the call to
BaseClass should be satisfied by the call in the Diamond constructor.
BaseClass doesn't have a default ctor. Therefore classes A and B
require the presence of a parametized ctor even though type Diamond
will invoke that parametized BaseClass ctor.
The issue is not whether the Diamond ctor 'satisfies' the
initialization of its base classes. The program has no choice but to
guarentee that an instance of A or B is properly generated. Its that
simple.
The above code says "BaseClass is not default constructeable". Why
should the program assume otherwise?
To correct the issue, provide a default ctor:
#include <iostream>
class BaseClass
{
int base_value;
public:
BaseClass(int bv = 0) : base_value(bv)
{
}
virtual ~BaseClass() { }
int value() const { return base_value; }
};
class A : public virtual BaseClass
{
public:
A() { }
~A() { }
};
class B : public virtual BaseClass
{
public:
B() { }
~B() { }
};
class Diamond: public A, public B
{
public:
Diamond(): BaseClass(3) { }
~Diamond() { }
};
int main(int argc, char* argv[])
{
Diamond d;
std::cout << "d.value() is ";
std::cout << d.value() << std::endl;
}
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]