473,656 Members | 2,824 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Inheriting the Wrong Constructor

struct base
{
int x, y, z;
base() {x = 0; y = 0; z = 0;};
base(int x1, int y1, int z1) {x = x1; y = y1; z = z1;};
};

struct intermediate1 : public virtual base {};

struct intermediate2 : public virtual base
{
intermediate2() : base(1,2,3) {};
};

struct derived : public virtual intermediate2, public virtual
intermediate1
{
derived() : intermediate2() {};
};

int main()
{
derived temp;
return 0;
}

OK, I know that classes don't actually inherit constructors. But it
sure seems like derived is inheriting something it shouldn't. When I
step through derived's instantiation I see that derived calls base's
default ctor and then calls intermediate2's ctor which does NOT call
base's custom ctor (I guess since it's already ctored). What I want
is derived to call intermediate2 to call base custom ctor. Why does
it do this, and how can I do what I want?
Aug 28 '08 #1
4 1690
Aa******@gmail. com wrote:
struct base
{
int x, y, z;
base() {x = 0; y = 0; z = 0;};
base(int x1, int y1, int z1) {x = x1; y = y1; z = z1;};
Read the FAQ. Prefer initialisation to assignment. Also, it would
seem that both constructors can be merged:

base(int x = 0, int y = 0, int z = 0) : x(x), y(y), z(z) {}

(and learn to omit the semicolons after function bodies).
};

struct intermediate1 : public virtual base {};

struct intermediate2 : public virtual base
{
intermediate2() : base(1,2,3) {};
};

struct derived : public virtual intermediate2, public virtual
intermediate1
{
derived() : intermediate2() {};
};

int main()
{
derived temp;
return 0;
}

OK, I know that classes don't actually inherit constructors. But it
sure seems like derived is inheriting something it shouldn't. When I
step through derived's instantiation I see that derived calls base's
default ctor and then calls intermediate2's ctor which does NOT call
base's custom ctor (I guess since it's already ctored). What I want
is derived to call intermediate2 to call base custom ctor. Why does
it do this, and how can I do what I want?
This has nothing to do with inheriting constructors, and everything with
the rule that the _most derived class_ is responsible for doing the
initialisation of the virtual base class[es].

'derived' has 'base' as virtual base class. That means it *itself* is
responsible for initialising the 'base' subobject. That means, in turn,
that in the initialiser list of 'derived' there *will be* the call to
'base::base()' (implicitly) if you don't specify explicitly what
constructor should be used. It is up to you to do it right, the
'derived' object cannot delegate the responsibility to any of its other
base classes. So, you ought to write

derived() : base(1,2,3) {}

if you wanted the particular values to be passed to 'base::base'.

HTH

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Aug 28 '08 #2
Read the FAQ. *Prefer initialisation to assignment. *Also, it would
seem that both constructors can be merged:

* * * base(int x = 0, int y = 0, int z = 0) : x(x), y(y), z(z) {}

(and learn to omit the semicolons after function bodies).
This has nothing to do with inheriting constructors, and everything with
the rule that the _most derived class_ is responsible for doing the
initialisation of the virtual base class[es].

'derived' has 'base' as virtual base class. *That means it *itself* is
responsible for initialising the 'base' subobject. *That means, in turn,
that in the initialiser list of 'derived' there *will be* the call to
'base::base()' (implicitly) if you don't specify explicitly what
constructor should be used. *It is up to you to do it right, the
'derived' object cannot delegate the responsibility to any of its other
base classes. *So, you ought to write

* * *derived() : base(1,2,3) {}

if you wanted the particular values to be passed to 'base::base'.

Thanks for the response but it's not the answer I was looking for. I
don't want the answer I can't or my design in insufficient, I want the
answer do x y z to get around it. So what is my reason to want the
base class initialized by an intermediate class rather than the
derived class? Because I'm using a policy based design. Let me
give you a more refined example, and again this is example code so no
need to worry about other critiques (I knew about all those and I read
the FAQ).

enum eShape {
circle,
triangle,
square
};

struct baseInteface
{
eShape shape;
baseInteface() {};
baseInteface(eS hape shape) {base::shape = shape;};
//other stuff related to interface
};

namespace Triangle {
struct InitPolicy : public virtual baseInteface
{
InitPolicy() : baseInteface(tr iangle){};
};
struct SomeOtherPolicy {};
};

namespace Square {
struct InitPolicy : public virtual baseInteface
{
int height, width;
InitPolicy() : baseInteface(sq uare){height = 0; width = 0;};
};
struct SomeOtherPolicy {};
};

template <
class shapePolicy,
class otherPolicy
>
struct Shape : public virtual shapePolicy, public virtual otherPolicy
{
Shape() : shapePolicy() {};
};

int main()
{
Shape<Triangle: :InitPolicy, Triangle::SomeO therPolicyshape ;
return 0;
}
Here, your suggestion of writing derived() : baseInteface(/*policy
data*/) {} violates my encapsulation, my derived class should not have
knowledge of the implementation of any of the policies, baseInteface
is the interface and derived is just the template conglomerator.

OK so you might ask me why don't you throw out all those policies and
intermediate classes and just have class Triangle inherit from class
Polygon? Because this is an example, I have too many derivations and
a policy based design cuts that number down. Or you might ask why not
just bite the bullet and use a virtual OnInit function? Well that's
what I tried at first, but C++ cannot call virtual functions from
farther down the inheritance tree in a constructor, because the object
further down doesn't exist yet!

So any ideas on how to have some intermediate policy init a base class
without the derived class knowing about it?

Aug 28 '08 #3
Aa******@gmail. com wrote:
[..]
Thanks for the response but it's not the answer I was looking for.[..]
If you're looking for a particular answer, you're in the wrong place.

Virtual base class subobjects are initialised by the most derived class.
Period. That's a requirement of the language, and you have to live
with it. If you missed it in my post, here it is again: the most
derived class initialises the virtual bases, all of them, either
explicitly (when you provide the initialiser in the initialiser list) or
implicitly (default, the compiler can do it for you). There is no way
around this *if* your base class is a *virtual base*. The reason why it
has to be that way is that if you have two paths which lead to the
single subobject of the virtual base type, and both have their own way
to initialise the base class subobject, then the compiler cannot pick
one or the other, *you* have to do it:

struct A { A(int); };

struct Intermediate1 : virtual A {
Intermediate1() : A(123) {}
};

struct Intermediate2 : virtual A {
Intermediate2() : A(456) {}
};

struct MostDerived : Intermediate1, Intermediate2
{
MostDerived() {} // what 'A' becomes? A(123) or A(456)?
};

The correct way:

struct MostDerived : Intermediate1, Intermediate2
{
MostDerived() : A(123) {} // or any other, like A(789)
};

Now that you know there is a limitation in the language with respect to
initialising virtual base classes, you need to look again at your design
or your implementation. Perhaps, just perhaps, you could do this:

struct A { A(int); };

struct Intermediate1 : virtual A {
static int initialiserForA () { return 123; }
Intermediate1() : A(initialiserFo rA()) {}
};

struct Intermediate2 : virtual A {
static int initialiserForA () { return 456; }
Intermediate2() : A(initialiserFo rA()) {}
};

struct MostDerived : Intermediate1, Intermediate2
{
MostDerived() : A(Intermediate1 ::initialiserFo rA()) {}
};

In which case the initialisation is still done in 'MostDerived', but the
actual value with which to initialised comes from some other place.

Please do not start your reply with "it's not the answer I was looking
for" again.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Aug 28 '08 #4
On Aug 28, 6:11 am, Aalaa...@gmail. com wrote:
Read the FAQ. Prefer initialisation to assignment. Also,
it would seem that both constructors can be merged:
base(int x = 0, int y = 0, int z = 0) : x(x), y(y), z(z) {}
(and learn to omit the semicolons after function bodies).
This has nothing to do with inheriting constructors, and
everything with the rule that the _most derived class_ is
responsible for doing the initialisation of the virtual base
class[es].
'derived' has 'base' as virtual base class. That means it
*itself* is responsible for initialising the 'base'
subobject. That means, in turn, that in the initialiser
list of 'derived' there *will be* the call to 'base::base()'
(implicitly) if you don't specify explicitly what
constructor should be used. It is up to you to do it right,
the 'derived' object cannot delegate the responsibility to
any of its other base classes. So, you ought to write
derived() : base(1,2,3) {}
if you wanted the particular values to be passed to
'base::base'.
Thanks for the response but it's not the answer I was looking for.
It's the correct answer, however.
I don't want the answer I can't or my design in insufficient,
I want the answer do x y z to get around it.
But that's what Victor just gave you. Specify the initializers
in the most derived class.
So what is my reason to want the base class initialized by an
intermediate class rather than the derived class?
Which intermediate class? You can have several intermediate
classes deriving from the same instance of the virtual base.

A long, long time ago, John Skaller, Fergus Henderson and I
discussed the possibility of requiring the compiler to determing
the lowest common derived class for each virtual base, and
calling the constructor there. In the end, we didn't follow
through with a proposal, because it requires a lot more
complexity in the compiler, and the cases where you would want a
non empty virtual base (requiring an initializer) are
exceedingly rare. (Note, however, that there is an example of
such in the standard library: basic_ios<>. If worse comes to
worse, you can always use something like is used in the iostream
hierarchy. Be forewarned, however, that it can be extremely
tricky to make it work without undefined behavior is some
special cases.)
Because I'm using a policy based design. Let me give you a
more refined example, and again this is example code so no
need to worry about other critiques (I knew about all those
and I read the FAQ).
enum eShape {
circle,
triangle,
square
};
struct baseInteface
{
eShape shape;
baseInteface() {};
baseInteface(eS hape shape) {base::shape = shape;};
//other stuff related to interface
};
namespace Triangle {
struct InitPolicy : public virtual baseInteface
{
InitPolicy() : baseInteface(tr iangle){};
};
struct SomeOtherPolicy {};
};
namespace Square {
struct InitPolicy : public virtual baseInteface
{
int height, width;
InitPolicy() : baseInteface(sq uare){height = 0; width = 0;};
};
struct SomeOtherPolicy {};
};
template <
class shapePolicy,
class otherPolicy
struct Shape : public virtual shapePolicy, public virtual otherPolicy
{
Shape() : shapePolicy() {};
};
int main()
{
Shape<Triangle: :InitPolicy, Triangle::SomeO therPolicyshape ;
return 0;
}
I don't quite see why you need, or even want, virtual
inheritance here. All of your shapePolicy should inherit from
baseInteface (which is in fact BasicShapePolic y). And no other
classes should. So you really don't want virtual inheritance
here.

[...]
So any ideas on how to have some intermediate policy init a
base class without the derived class knowing about it?
In simple cases like this, you can simply use an init() member
function, calling it where ever you want.

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Aug 31 '08 #5

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

Similar topics

5
6879
by: Andy Jarrell | last post by:
I'm trying to inherit from a specific class that has an overloaded operator. The problem I'm getting is that certain overloaded operators don't seem to come with the inheritance. For example: // TestA.h --------------------------------------- #include <iostream> enum Aval { FIRST_VALUE,
11
2160
by: Noah Coad [MVP .NET/C#] | last post by:
How do you make a member of a class mandatory to override with a _new_ definition? For example, when inheriting from System.Collections.CollectionBase, you are required to implement certain methods, such as public void Add(MyClass c). How can I enforce the same behavior (of requiring to implement a member with a new return type in an inherited class) in the master class (similar to the CollectionBase)? I have a class called...
1
4482
by: Maheal | last post by:
I have been trying to Serialize an object that is the child of another object which is also serializable. Here is the simplified scenario (assume missing code is correct): class One : ISerializable { int x; int y; One() {}; // constructor One(SerializationInfo i, StreamingContext c) { // deserialization
3
2518
by: sureshsundar007 | last post by:
Hi all, I'm trying to inherit the SimpleWorkerRequest class but cant able to do so. I'm getting an error called "System.Web.Hosting.SimpleWorkerRequest.SimpleWorkerRequest()' is inaccessible due to its protection level" I tried my dervived class with public,internal and private
3
1672
by: G. Purby | last post by:
What is the proper way of defining a class that inherits from a base class that has no constructor with 0 arguments? The following code generates compiler error CS1501, "No overload for method 'BaseClass' takes '0' arguments". class BaseClass { public BaseClass(double x) {
1
1670
by: DanielSchaffer | last post by:
I am trying to create a class that inherits fromControlCollection, but I am getting the compile error "Nooverload for method 'ControlCollection' takes '0' arguments",and VS highlights the constructor method: public AvailabilityCollection(Control owner) { _owner = owner; } Here is what the .NET SDK has for the ControlCollectionconstructor: public ControlCollection( Control owner );
2
1619
by: Jim Heavey | last post by:
I amd playing around with inheritance a little in VB.Net If I create a new class which inherits from ListViewItem and I am only wanting to override the ToString Method. In this situation, If I only override the "ToString" method, I find that I only have a single constructor. Do I have to clone all of the constructor methods and then execute the MyBase.New(....) methods for each of those constructors? If I am inheriting all methods and...
4
5546
by: l.s.rockfan | last post by:
Hello, how do i have to call an inherited, templated class constructor from the initializer list of the inheriting, non-templated class constructor? example code: template<typename T> class A
3
1945
by: srinivasan srinivas | last post by:
Hi, I am getting an error while executing the following snippet. If i comment out method __repr__ , it works fine. class fs(frozenset):     def __new__(cls, *data):         data = sorted(data)         self = frozenset.__new__(cls, data)         self.__data = data         return self
0
8816
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
8717
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 captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
8600
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
7311
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...
1
6162
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5629
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 into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4150
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
4300
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
1930
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.