Does a subclass need a default constructor? - c++

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.

Related

Forbid users to create objects but allow some classes

I have the following two classes.
Class A
{
proctected:
A(){}
};
Class B
{
push_new_A_into_v();
vector<A> v;
};
The function
push_new_A_into_v();
will not compile since A's constructor is protected. To make B inherit from A will not help since the method create a completely new A(Why is protected constructor raising an error this this code?).
The reason A's constructor is protected is to make users unable to create an object of type A.
How can I make it possible for the method to work while users is still unable to create objects of type A?
In addition to user2913094's answer:
If giving B full friendship just to allow construction seems unacceptable, you can add a constructor that requires a construction token, which can only be obtained by B:
class A {
public:
class ConstructionToken {
private:
ConstructionToken();
friend class B;
};
A(ConstructionToken const&);
protected:
A();
};
Note that the token class is completely empty, but since only B can access its private constructor, that essentially prevents the user of invoking A's public constructor directly.
This allows for more fine-grained access control, but has the disadvantage that it requires introducing an additional constructor overload on A.
class A {
friend class B;
...

Is this constructor correct?

I have two classes A and B, and in class A I have an member of type B:
class B {
public:
B(); //default constructor
};
class A {
public:
A(); //constructor
B b;
};
This is the definition of class A's constructor:
A::A() : b()
{}
Here, I tried to initialize b using the initialization list. My question is, is this way to initialize b correct, or am I just creating another temporary object named b inside the constructor of A that has nothing to do with A::b?
This is correct. However, since b is of class type, the default constructor will be called automatically if b isn't mentioned in A::A's initialization list, so you don't need to mention it at all.
This method will initialize the field b with the constructor B::B(). It does not create a temporary local.
Note that in this particular case it's also unnecessary. The default constructor generated for A will do this by itself. There is nothing wrong with being explicit here, it's just unnecessary

inheriting constructors of class virtually derived.

I came across this question which asks its output.
#include<iostream>
using namespace std;
class A{
public:
int i;
A(int j=3):i(j){}
};
class B:virtual public A{
public:
B(int j=2):A(j){}
};
class C:virtual public A{
public:
C(int j=1):A(j){}
};
class D:public B, public C {
public:
D(int j=0):A(j), B(j+1), C(j+2){}
};
int main()
{
D d;
cout<<d.i;
return 0;
}
There are few things which I did not understand.
Please clarify these doubts.I could not google it as I did not know what to search for.
Q1. As in the code a parameterised constructor is used.Just after the colon(:) we write the constructor of the parent class.How
A(int j=3):i(j){}
is used? As i is not a class.
Q2. In the class D, the constructor for the class is using the constructors for initialising the base classes.But as it can be seen that all the constructors modify variable i of the class A only.
Then what is the sequence of the constructor calling here.
I know when we do not call the constructor of the parent class, it is explicitly called and the order is well known, but what when we implicitly call the constructor like here.
Q3. Inspite of the parameters being initialized, the value which we send in the constructor seems to make a difference.Why is it so ?
A1. :i(j) in A(int j=3):i(j){} is an initializer list. Initializer lists can specify how parent classes and member variables are initialized. (j) is the initializer for i and behaves similarly to initialization for a local variable: int i(j);. (you may be more familiar with the initialization syntax int i = j; which is similar. You can't use the = syntax in initializer lists.)
A2. Virtual base classes are always initialized exclusively by the most derived class's constructor. So D's constructor initializes its A base class and when D's constructor calls the constructors for B and C those constructors do not reinitialize A.
A3. The syntax D(int j=0) does not initialize the parameter. Instead it declares a default value for the parameter which is ignored whenever you explicitly pass a value for that parameter.
The ctor-initializer-list contains the initializers for all subobjects. That means base class subobjects and member subobjects.
Subobjects are initialized in the order in which they appear in the class definition, always. it doesn't matter what order you put them in the ctor-initializer-list (although putting them in any other order is confusing when the order is ignored).
Inherited base subobject constructors are called by the constructor of the class which is directly derived... except for virtual base subobjects, which are called directly from the constructor for the most-derived object. Virtual base subobjects are constructed before anything else.
There's no such thing as "parameters being initialized". Those are default arguments, and they are ignored when an actual argument is provided.
1) The colon : can be used in a constructor to call the constructors of member variables with the given arguments:
public:
int i;
A(int j=3):i(j){}
means that A's member i will call its constructor with j as the argument.
2) Subobjects will be initialized in the order they appear in the class definition
class D:public B, public C
3) They weren't initialized, they were given default arguments.
Q1:
That code in the constructor between the signature of the function and before the opening bracket of the function body is called an initializer list.
The syntax of an initializer list is a listing of member variables of the class with corresponding initial values. The initial values are in parenthesis. The member variables are separate by comma's. The first variable comes after a colon.
An initializer list can also include a constructor to base class, which is what your B and C class do. Your 'A' class simply uses the form that initializes a member variable.
Q2:
To find the order that the constructors are executed in, put in some print statements. It will help you understand the order of construction. Also put in a destructor and put print statements in those too. I can't do all of your homework for you on this question. :)
Q3:
I guess by parameters being initialized you mean the default arguments? Default arguments are always always overridden if a value is actually passed into the function.

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

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..
//...
};

Is it true that a default constructor is synthesized for every class that does not define one?

If the class doesn't have the constructor, will the compiler make one default constructor for it ?
Programmers new to C++ often have two common misunderstandings:
That a default constructor is synthesized for every class that does
not define one
from the book Inside the C++ Object Model
I am at a loss...
This is well explained in the section from which this quote is taken. I will not paraphrase it in its entirety, but here is a short summary of the section content.
First of all, you need to understand the following terms: implicitly-declared, implicitly-defined, trivial, non-trivial and synthesized (a term that is used by Stanley Lippman, but is not used in the standard).
implicitly-declared
A constructor is implicitly-declared for a class if there is no user-declared constructor in this class. For example, this class struct T { }; does not declare any constructor, so the compiler implicitly declares a default constructor. On the other hand, this class struct T { T(int); }; declares a constructor, so the compiler will not declare an implicit default constructor. You will not be able to create an instance of T without parameters, unless you define your own default constructor.
implicitly-defined
An implicitly-declared constructor is implicitly-defined when it is used, i.e. when an instance is created without parameters. Assuming the following class struct T { };, the line T t; will trigger the definition of T::T(). Otherwise, you would have a linker error since the constructor would be declared but not defined. However, an implicitly-defined constructor does not necessarily have any code associated with it! A default constructor is synthesized (meaning that some code is created for it) by the compiler only under certain circumstances.
trivial constructor
An implicitly-declared default constructor is trivial when:
its class has no virtual functions and no virtual base classes and
its base classes have trivial constructors and
all its non-static members have trivial constructors.
In this case, the default compiler has nothing to do, so there is no code synthesized for it. For instance, in the following code
struct Trivial
{
int i;
char * pc;
};
int main()
{
Trivial t;
}
the construction of t does not involve any operations (you can see that by looking at the generated assembly: no constructor is called to construct t).
non-trivial
On the other hand, if the class does not meet the three requirements stated above, its implicitly-declared default constructor will be non-trivial, meaning that it will involve some operations that must be performed in order to respect the language semantics. In this case, the compiler will synthesize an implementation of the constructor performing these operations.
For instance, consider the following class:
struct NonTrivial
{
virtual void foo();
};
Since it has a virtual member function, its default constructor must set the virtual table pointer to the correct value (assuming the implementation use a virtual method table, of course).
Similarly, the constructor of this class
struct NonTrivial
{
std::string s;
};
must call the string default constructor, as it is not trivial. To perform these operations, the compiler generates the code for the default constructor, and calls it anytime you create an instance without parameters. You can check this by looking at the assembly corresponding to this instantiation NonTrivial n; (you should see a function call, unless the constructor has been inlined).
Summary
When you don't provide any constructor for your class, the compiler implicitly declares a default one. If you try to use it, the compiler implicitly defines it, if it can (it is not always possible, for instance when a class has a non-default-constructible member). However, this implicit definition does not imply the generation of any code. The compiler needs to generate code for the constructor (synthesize it) only if it is non-trivial, meaning that it involves certain operations needed to implement the language semantics.
N.B.
Stanley B Lippman's "Inside the C++ object model" and this answer deals with (a possible) implementation of C++, not its semantics. As a consequence, none of the above can be generalized to all compilers: as far as I know, an implementation is perfectly allowed to generate code even for a trivial constructor. From the C++ user point of view, all that matters is the "implicitly-declared/defined` aspect (and also the trivial/non-trivial distinction, as it has some implications (for instance, an object of a class with non-trivial constructor cannot be a member of a union)).
I think the misconception is:
That a default constructor is synthesized for every class that does not define one
That people think the default constructor, which accepts no arguments, will always be generated if you don't declare it yourself.
However, this is not true, because if you declare any constructor yourself, the default one will not be automatically created.
class MyClass {
public:
MyClass(int x) {}; // No default constructor will be generated now
};
This will lead to problems like when beginners expect to use MyClass like this:
MyClass mc;
Which won't work because there is no default constructor that accepts no args.
edit as OP is still a little confused.
Imagine that my MyClass above was this:
class MyClass {
};
int main() {
MyClass m;
}
That would compile, because the compiler will autogenerate the default constructor MyClass() because MyClass was used.
Now take a look at this:
#include <iostream>
class MyClass {
};
int main() {
std::cout << "exiting\n";
}
If this were the only code around, the compiler wouldn't even bother generating the default constructor, because MyClass is never used.
Now this:
#include <iostream>
class MyClass {
public:
MyClass(int x = 5) { _x = x; }
int _x;
};
int main() {
MyClass m;
std::cout << m._x;
}
The compiler doesn't generate default constructor MyClass(), because the class already has a constructor defined by me. This will work, and MyClass(int x = 5) works as your default constructor because it can accept no arguments, but it wasn't generated by the compiler.
And finally, where beginners might run into a problem:
class MyClass() {
public:
MyClass(int x) { _x = x; }
int _x;
};
int main() {
MyClass m;
}
The above will throw you an error during compilation, because MyClass m needs a default constructor (no arguments) to work, but you already declared a constructor that takes an int. The compiler will not generate a no-argument constructor in this situation either.
A default constructor is synthesized for every class that does not define one if:
The code using the class needs one & only if
There is no other constructor explicitly defined for the class by you.
All the upvoted answers thus far seem to say approximately the same thing:
A default constructor is synthesized for every class that does not have any user-defined constructor.
which is a modification of the statement in the question, which means
A default constructor is synthesized for every class that does not have a user-defined default constructor.
The difference is important, but the statement is still wrong.
A correct statement would be:
A default constructor is synthesized for every class that does not have any user-defined constructor and for which all sub-objects are default-constructible in the context of the class.
Here are some clear counter-examples to the first statement:
struct NoDefaultConstructor
{
NoDefaultConstructor(int);
};
class Surprise1
{
NoDefaultConstructor m;
} s1; // fails, no default constructor exists for Surprise1
class Surprise1 has no user-defined constructors, but no default constructor is synthesized.
It doesn't matter whether the subobject is a member or a base:
class Surprise2 : public NoDefaultConstructor
{
} s2; // fails, no default constructor exists for Surprise2
Even if all subobjects are default-constructible, the default constructor has to be accessible from the composite class:
class NonPublicConstructor
{
protected:
NonPublicConstructor();
};
class Surprise3
{
NonPublicConstructor m;
} s3; // fails, no default constructor exists for Surprise3
Yes a default constructor is always there by default if you don't define a constructor of your own (see the default constructor section here).
http://www.codeguru.com/forum/archive/index.php/t-257648.html
Quote:
The following sentense are got from the book "Inside the C++ object model" , written by Stanley B. Lippman.
There are four characteristics of a class under which the compiler
needs to synthesize a default constructor for classes that declare no
constructor at all. The Standard refers to these as implicit,
nontrivial default constructors. The synthesized constructor fulfills
only an implementation need. It does this by invoking member object or
base class default constructors or initializing the virtual function
or virtual base class mechanism for each object. Classes that do not
exhibit these characteristics and that declare no constructor at all
are said to have implicit, trivial default constructors. In practice,
these trivial default constructors are not synthesized. ...
Programmers new to C++ often have two common misunderstandings:
That a default constructor is synthesized for every class that does
not define one
That the compiler-synthesized default constructor provides explicit
default initializers for each data member declared within the class
As you have seen, neither of these is true.