Does this work? C++ multiple inheritance and constructor chaining - c++

Consider a class Waldo, that inherits from Foo and Baz, viz.:
class Waldo : public Foo, public Baz {
...
};
When I create a new instance of Waldo:
Waldo *w = new Waldo;
do the Foo and Baz constructors get called? If they are not called by default, is there an easy way IN THE CLASS DECLARATION OR IN THE DECLARATION/DEFINITION of the Waldo constructor to force them to be called?
(It looks like I may be trying to do constructor chaining, and C++ allegedly doesn't do that. I'm not sure.)
What I'm trying to do is "annotate" various class declarations, where the annotations cause (among other things) instances of the annotated class to be linked into lists maintained by the annotation classes. This lets me, for example, walk the list of all objects with Baz-nature, applying a certain operation to them, and not have to worry about whether I remembered to add the instance to the list of objects with Baz-nature, because the constructor did it automagically.

Yes, they are called. Left to right.

The constructors of all the members of a class are called in the order they are declared in the class.
The default constructors of derived classes call the constructors of base class by default. If they need arguments, they need to be invoked explicitly else it is an error...
class Employee {
private:
//
public:
Employee();
//...
};
class Manager: public Employee {
private:
short level;
public:
Manager(): Employee(), level() {} // This is the default constructor, it calls Employee().
// The definition is equivalent to default constructor of Manager..
//...
};

Related

Does a subclass need a default constructor?

I am learning about inheritance right now, and there is one thing I haven't found a solid answer on. If I have three classes one being a super and two subclass, would my subclasses need a default constructor if they inherit the same fields? Class b doesn't have a default constructor because it inherits its fields from A, where as class c has different fields, therefore it would need its own default constructor.
class A {
private:
int a;
int b;
public:
A();
A(int, int);
};
class B: public A {
public:
B(int, int);
};
class C : public A {
private:
int c;
public:
C();
C(int, int);
};
anything is greatly appreciated.
If [irrelevant], would my subclasses need a default constructor if [irrelevant]?
That depends on how your subclasses are used. If – and only if – you need to construct an instance of your class without providing construction parameters, then that class needs a default constructor. Whether or not you need to explicitly define (or forward via using) a default constructor depends on whether or not other constructors are defined, and on whether or not that constructor has something non-trivial to do. This topic should have been covered long before inheritance.
There is, however, a new caveat when inheritance enters the picture. Since I cannot tell if you use member initialization lists, I recommend reading No Matching Function Call to Base class. If you do not use member initialization lists, your derived classes will construct their bases without construction parameters. However, note that it is usually better to address this situation by using initialization lists rather than adding a default constructor.
Class b doesn't have a default constructor because it inherits its fields from A,
No, class B doesn't have a default constructor because it defines a non-default constructor. The non-default constructor prevents the compiler from supplying a default constructor. If your code successfully compiles, one can conclude that B does not need a default constructor.
where as class c has different fields, therefore it would need its own default constructor.
Whether or not a class has fields is irrelevant to "need". (Fields may make it more likely that an explicit default constructor is appropriate since there might be data to initialize, but their mere existence does not dictate a need.)
A class should have a default constructor if you intend for calling code to be able to use a default constructor and create an instance of the class without passing additional arguments to it. B won't automatically get A's default constructor just because B adds no additional member variables.
B won't automatically have a default constructor just because A has one and B doesn't have any new variables. If you want to forward A's default constructor, you can do so with a using declaration like so:
class A {
private:
int a;
int b;
public:
A();
A(int, int);
};
class B: public A {
public:
using A::A; // All of A's constructors are now publically usable as B constructors
};
Note that I removed the declaration B(int, int); because the using declaration brings both constructors forward from A. If you want B(int, int); to do something different than A(int, int);, you can declare B(int, int); alongside the using declaration and the more derived constructor will shadow the inherited constructor.

Does it make sense to have a class without constructor?

I am wondering whether it makes sense to have a class without constructor if the derived classes have one. If not, is there a way of doing what I want differently?
My case is the following:
I want the users to only use the derived classes, but those have data members and methods in common.
EDIT: as default constructors exist for classes, it means that the user can always create an instance of Instrument directly, then how can I do what I want?
class instrument{
public:
double get_price();
std::string get_udl();
private:
double m_price;
std::string m_udl;
};
class stock : public instrument{
public:
double get_dividend();
private:
double m_dividend;
};
class option : public instrument{
public:
double get_strike();
private:
double m_strike;
};
I want the users to only use the derived classes, but those have data members and methods in common
Have your default (or any other) c'tor, but declare it with protected access. Now only derived classes may invoke it. Effectively making it usable only when inherited.
class instrument{
public:
double get_price();
std::string get_udl();
protected:
instrument() = default;
private:
double m_price;
std::string m_udl;
};
This also avoids the overhead associated with making a class abstract. If you don't need polymorphism, you shouldn't use it just to make a class usable only as a base class.
Have thought of Abstract class ?
An abstract class is a class that is declared abstract—it may or may not include abstract methods. Abstract classes cannot be instantiated, but they can be subclassed.
Isn't this what you are looking for ?
When there's no default constructor defined, the compiler will automatically generate one for you, doing nothing for members of basic types and calls the default constructor for members of struct/class types.
So the conclusion is, it makes no sense to have a class without any constructor because whenever you define an instance of that class you have to call at least one (more may be called with deligate construction).
Yes! Definitely it make sense. Because when user create the instance of derived class, first of all parent class's constructor will be called from within the derived class constructor. Even without you explicitly call it. And parent class's default constructor will be called even if you didn't create one. By default
public constructor with no parameter is present in every class
if it has no overridden constructor.
And yes all the public members of parent class will be present in derived class after creating derived class instance.

Inherited class data members

I am a bit confused, i was reading this C++ Constructor/Destructor inheritance, and so it says constructors and destructors are not inherited from the base class to the derived class but the constructors and destructors are called when i create a derived object. So is the constructors and destructors of the base class data members of the inherited classes?
Constructors and destructors are very special animals; in fact, the Standard identifies them as "Special Member Functions."
All the things that are weird and unique about constructors and destructors (for example, the fact that they don't have "names" and the fact that they aren't "inherited") is really quite irrelevant to almost all programming and programmers. Here is what you need to know:
Constructors and destructors are not member variables (obviously) -- they are (special) member functions.
When you derive from a base class, some constructor of the base class is going to be called. Which constructor depends on how you've written your code. If you don't explicitly specify which constructor to call, the default constructor will be called. This happens in your derived object's initialization list, even if you haven't written one.
You may specify another constructor through an initialization list, only:
class Bar : public Foo
{
public:
Bar()
:
Foo (1, 2, 3)
{
}
};
Here, Bar's initialization list specifies a constructor on Foo which takes 3 parameters convertible from integrals. One such constructor might be:
class Foo
{
public:
Foo (int a, long b, unsigned c)
:
mA (a),
mB (b),
mC (c)
{
}
private:
int mA;
long mB;
unsigned mC;
};
Back to the Bar example above. By the time the initialization list is done executing, and before the body of Bar's constructor starts, all of Bar's base classes and member variables have already been instantiated and initialized. This is why the only way to specify some constructor for Foo other than the default constructor is through an initialization list -- which, in turn, is why you must have an initialization list if the base class has no default constructor available.
Question: If constructors and destructors are not inherited, then why are they called when instantiating a derived type?
Answer: Because constructors are what initialize objects, and a derived type has an IS-A relationship with the base type.
Consider Foo and Bar above again. Bar derives from Foo, so in a sense Bar IS A Bar. It's more than just a Foo, it's got stuff that Foo doesn't have; but it has all the Foo-ness. Since a Bar object is in part a Foo, that Foo-ness has to be initialized. Since all initialization ob objects is done through a constructor, Foo's constructor must be called.
So, constructors and destructors aren't inherited in the sense of overloading -- but the constructors of the base class will be called. They have to be. Otherwise the Fooness of a Bar object could never come to be.
When you are deriving from a base class, something that you will often want to do is pass around a pointer to the base class. In fact, you may not need a pointer to the derived type at all in many cases. This is especially true when designing abstract interfaces.
There is a nasty problem that can come up when you do this and haven't taken all the needed preperations. Consider:
class Foo
{
public:
std::string mS;
};
class Bar : public Foo
{
public:
long mArray[0xFFFF]; // an array of 65K longs
};
int main()
{
Foo* thingy = new Bar; // Totally OK
// ... do stuff...
delete thingy; // WHOOPS! Memory leak!
}
Above in the delete call we're deleting through a base class pointer. The Foo destructor (which is implicit) is properly called, but the Bar destructor is not -- leaving that huge array of 65K longs leaked.
To fix this, we need to give Foo a virtual destructor:
class Foo
{
public:
std::string mS;
virtual ~Foo() {}
};
This doesn't do much, but it does one critical thing: it sets up polymorphism so that when we call the destructor (implicitly), the virtual override will get called.
This is a critical step when designing a class hierarchy. If you think there is any chance that people will pass around pointers to the base class, you should have a virtual destructor in the base class. In fact, I would suggest that in almost every case you should have a virtual destructor even if you don't think people will use it this way.
No. As you said, constructors and destructors are not inherited (by the way, the assignment operator isn't either). It would be logically flawed if they were inherited, right? Constructors (and destructors) are specific for that exact class; and since the derived class usually has something specific and new, the base constructor is not enough to initialize the inherited class objects.
So why is the base constructor called when creating an object of the child class?
Well, every derived object has a sub-object - which is the actual object of the parent class (I hope this sentence wasn't difficult to understand).
The compiler will:
1) locate the constructor of the derived class whose list of initializers best fits the arguments passed, but not execute it;
2) execute the constructor of the base class to create the sub-object;
3) execute the constructor of the derived class, to create the actual object.
I hope this is clear; you can find a much more detailed explanation in the answer above :)

nested class inherits from nested class

I wanted the class C inherits from class A its virtual functions, and class D(nested class in class C) inherits from class B(nested class in class A) its data fields, here is what I have.
file1.h
class A{
public:
virtual void foo()=0;
class B{
public:
int data;
};
};
file2.h
class C : public A{
public:
class D : public A::B{
};
};
file2.cpp
void C::foo(){//code}
C::D::D():data(0){//Bad initialization list, error being data is not a member of C::D even it should inherits from its base class
data = 0; //good! compiler can see data is a member of A::B,and C::D inherits from it
}
I got two questions, first one is that is what I am doing the correct way to achieve this kind of inheritance. Secondly, as I commented, why compiler can see data is from A::B in the manual initialization process but not in the initialization list? Shouldn't them be in the same scope? Thank you very much
Edit1:
So if class C::D(foo) doesn't directly inherits from A::B(foo), but C inherits from A, my perception is that since C inherits from A and all its public fields, including its inner class A::B(foo), D(foo) has the exactly same name as A::B(foo) and is an inner class of C, like this, i.e used foo for both inner classes
class A{
public:
class foo{
public:
int data;
};
};
class C : public A{
public:
class foo{
};
};
Would it be confusing for the compiler when I call the C::foo directly? since there are two constructors with the name in the scope? or it chooses to call the "nearest" one, e.g C:foo? instead of climbing up the inheritance chain? Thank you very much
Yes, your approach is the correct way to achieve this kind of inheritance.
Initializer lists are there to control the arguments passed to the constructor. You can pass arguments to B's constructor, but not directly initialize a member of B (it's the job of its constructor). If there is no constructor specified for a base class or a member, the default constructor is used.
In your case, add a constructor to B to achieve what you want.
class A {
public:
class B{
public:
B(int i) : data(i) {}
int data;
};
};
class C : public A {
class D : public A::B {
};
};
C::D::D() :B(0) { }
From a syntactical point of view, it's correct(*1). Apart, of course, from the initialization list. You can only initialize current-class members (not base-class members) in the initializer list. That has nothing to do with the nesting.
class X
{
public:
int x;
};
class Y : X
{
Y() : x(0) {} //still illegal
};
I said syntactical POV because it's a weird thing to do... I'm sure there's a cleaner way to achieve what you actually want.
Your syntax for inheriting from a nested class is correct.
An initializer list is for initializing that class's members; base class members should be initialized in a base class constructor.
Syntactically, the accepted answer has answered your questions very well.
Here's my two cents on the design aspect related to the mechanism:
In your example abstract class A is essentially an interface. An interface should define behavior and behavior only. That being said, I don't think it makes sense to have a nested class in an interface.
1) an interface does not have any data member to be manipulated by the nested class, as is the case with your example. This eliminates the need for a nested class in the first place.
2) a nested class is not a behavior. So it shouldn't appear in an interface.
Now you may argue that your example is just a quick demonstration, and in reality you would have data members for the nested to manipulate, i.e. class A is not a pure interface. You simply want to provide a default implementation for the nested class B and let the class C decides how he wants to customize class B into his own class D. If that's the case I'm afraid the design is even worse.
3) Consider the iterator pattern. Class A is essentially an abstract container that can't be instantiated(because you have a pure virtual function in it) - let's map it to IContainer in our mind. Now you create a class C which has a vector/array implementation, with his own iterator D pointing to some element in the array.
Then you want create another class E which has a hash map implementation, with her own iterator F pointer to some pair in the hash map.
Here's the disaster: very often you cannot have a uniform interface across all the iterator classes(D, F ...) in the implementations of the containing classes(C, E ...) - very likely(consider the assignment operator: BIterator operator=(const BIterator& other);), class D has a function which accepts a class D object as argument: DIterator operator=(const DIterator& other); class F has some function that accepts a class F object as argument: FIterator operator=(const FIterator& other).
On the other hand, this wouldn't work because both DIterator and FIterator are sub-classes of BIterator - You can't override a function with 'narrower'(or 'more specific') arguments as it violates the contravariance of argument types(C++ does not allow contravariant arguments, so it requires matching argument types; so technically you can have FIterator operator=(const BIterator& other) for class F and do a run-time dynamic cast from BIterator to FIterator - but that's ugly and it doesn't make sense: a concrete apple has an assignment operator that assigns an abstract 'fruit' to itself). You just got yourself in a dilemma.
To sum up, due to reasons 1) 2) and 3), don't include a nested class in an interface/abstract base class. The iterator pattern is just an example, there could be numerous occasions on which you shoot yourself in the feet as long as the nested classes interact with the containing classes. If not, then there's no point in having nested classes in the first place.

Why does a purely virtual/abstract class require a constructor, in particular for protected const member variables?

I have a purely virtual class defined as such:
class BaseClass {
protected:
const int var;
public:
void somefun() = 0; // what I mean by a purely virtual class
// stuff...
};
If I don't add a constructor defined as such:
BaseClass(const int & VAR) : var(VAR) {};
that I would have to subsequently use in ever derived class, my derived class can't initialize the const variable var to whichever value it wants to. Now I actually understand what's going on here. Before constructing a derived class, a constructor of the base class is called, at which point const member variables must be initialized. My question is not a "how do I make my code work" kind of question, that's already been done. My question is about why the compiler thinks it's necessary. For a purely virtual class, shouldn't I be allowed to write something like:
class DerivedClass : BaseClass {
public:
DerivedClass() : var(SOME_VALUE) {};
}
If the compiler knows that a call to a BaseClass constructor will necessarily be followed by a call to some derived class constructror (since an object of abstract type can never be instantiated) shouldn't it give us a bit more leeway?
Is this all a consequence of how C++ chooses to get around the Diamond problem? Even if that was the case, shouldn't the compiler at least somehow allow for the possibility that const member variable of purely virtual functions will be defined in derived classes? Is that too complicated or does that mess with the C++ solution to the Diamond problem?
Thanks for the help everyone.
It's not "purely virtual" (whatever you mean by that) - it contains a data member.
Class members can only be initialised by the initialiser list of a constructor of that class, not of a derived class. That's how object initialisation is specified: all members that are initialised, are initialised before the constructor body begins.
Constant objects must be initialised, since they can't be assigned a value later.
Therefore, a class with a constant data member must initialise it in each constructor.
For a purely virtual class, shouldn't I be allowed to write something
like
No, but you can(and in this case should) write something like this:
class DerivedClass : BaseClass {
public:
DerivedClass() : BaseClass(SOME_VALUE) {};
};
The construction of an object occurs in a specific order. The base class must be fully constructed before the constructor of a derived class is run, so that the derived constructor is working with a fully formed and valid base object. If the initialization of base member variables were put off until the construction of the derived class, this invariant would be broken.