If my base class's constructor takes parameters, how do I create a class that inherits from it, and executes the base class's constructor using the derived class's constructor?
For example, assuming my base class's instructor takes an integer, and does a cool trick with it, how would I make it so all classes that inherit from it can do the same
Pseudo-code
baseClass instance(99); //does an awesome trick, nice
derivedClass instance(99); //<-- should do the same as above
As I have it now, I have my base class's constructor defined, but for the derived class, I left its constructor blank, since I want it to do exactly what the base constructor does, and nothing more. But, this gave me an error along the lines of: no matching function call to the 'baseClass()', candidates are: baseClass(int), candidate expects 1 argument, 0 provided
Do I have to make the base class's constructor virtual or something?
This is easy in the current C++ standard, but it still requires some action on your part:
struct baseClass
{
explicit baseClass(int);
};
struct derivedClass : baseClass
{
using baseClass::baseClass; // inherit *all* of baseClass' constructors
};
In the previous standard, C++03, you have to implement the constructor in the derived type and call the base class's one in the initialization list:
struct derivedClass : baseClass
{
explicit derivedClass(int i) : baseClass(i) {}
};
Note: I use struct here to save typing: default member access and inheritance is public.
The idea is that derivedClass will need to call baseClass constructor anyway, since it needs to to complete its construction. The error you get is due to the fact that, without calling a the base constructor explicitly, the compiler is trying to call the default one.
However, in your case, it does not exist, since you already defined a constructor that takes an int. To do what you want, a solution could be to do this:
class derivedClass : baseClass {
public:
derivedClass(int x) : baseClass(x) {}
};
Related
Consider the following:
I derive a class Child from another class Parent. Parent has a ton of overloaded constructors. The Child class does not need any more parameters for construction. But once the base class constructor has been called, I want to do some more stuff during object construction.
So my question is: Using Modern C++, can I write a single constructor that accepts all arguments that any of the overloaded base class constructors accept and just forwards them to the respective one?
To be explicit: I am aware of the using Parent::Parent syntax, but that would not give me the opportunity to do anything after the base class constructor is called, as far as I understand.
I have searched around here on SO and in the depths of the internet, but I could not find anything like that, even though it seems like a fairly common use case to me. Any help would be much appreciated.
One way you could do this is to make a variadic template constructor in the derived class that passes all of its arguments to the base class. Then you can do whatever additional stuff you want in the body of that constructor. That would look like
struct Base
{
Base (int) {}
Base(int, int) {}
//...
};
struct Derived : Base
{
template<typename... Args>
Derived(Args&&... args) : Base(std::forward<Args>(args)...) // <- forward all arguments to the base class
{
// additional stuff here
}
};
class Base {
public:
Base(int a) : a_(a) {
//do something
someMethod();
//do something else
};
protected:
int a_;
virtual void someMethod() = 0 {};
};
class Derived : Base {
public:
Derived() {
Base::Base(42);
}
protected:
void someMethod() override {
//realisation
}
};
int main() {
Derived *obj = new Derived();
delete obj;
}
This code doesn't work by two mistakes: base class's default constructor is needed and base class's constructor with parameters can't be called because of using abstract methods
My problem is that someMethod() realised in class Derived is not called at all when I create object of class Derived. Also I don't want to use default constructor of class Base, but compiler is swearing.
How can I correct my code to see functionality that I want?
How can I correct my code to see functionality that I want?
Remove the call to a pure virtual function in the constructor of Base.
Call someMethod in the constructor of the derived class that overrides it instead.
Provide an initialiser to the Base subobject in the member initiliser list. If you don't provide an initialiser to the base, it will be default initialised.
Why this cannot work ?
This design will not work because of the way obects are constructed.
When you construct a Derived, the first thing happening is that a Base object is constructed with a Base constructor. There is no Derived object at this moment, so if you'd invoke the virtual function in the Base constructor, it would be the virtual that would be valid for the Base class until you leave the Base constructor's body.
This is allowed by the standard, but with restrictions:
[base.class.init]/16: Member functions (including virtual member functions) can be called for an object under construction. (...) However,
if these operations are performed in a ctor-initializer (or in a
function called directly or indirectly from a ctor-initializer) before
all the mem-initializers for base classes have completed, the program
has undefined behavior.
These restriction do not apply to virtual functions that are called from the constructor body, since the body is executed after all initializers.
But in your case the virtual function is pure virtual for the Base. So it's UB according to the following clause:
[class.abstract]/6: Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making
a virtual call to a pure virtual function directly or
indirectly for the object being created (or destroyed) from such a
constructor (or destructor) is undefined.
What is the alternative
There is unfortunately no other real alternative than using a two step initialization in which you first construct the object and then call an initialization function before using the object.
The only issue with this approach is the risk of forgetting the call to the initialization function. You can protect you against this:
using a flag to indicate if the intialization has taken place and check this flag in all member functions (yes, it's a little overhead).
if you have an abstract class, you may perhaps use a factory pattern (factory method or abstract factory). You could then let the factory do the call.
you may use the builder pattern, and make sure that the constructor is only visible to the builder who won't forget the initialization either.
Other problems with your code
You must be careful about how you "call" the base constructor from the derived constructor:
class Derived : Base {
public:
Derived() : Base(42) // this is the correct place !
{
//Base::Base(42); //<==== OUCH !!! NO !! This creates a temporary base object !!
}
...
};
You'd also need to be careful about the pure virtuals (I don't know if it's a typo or if your compiler could compile your code):
virtual void someMethod() = 0; // if it's abstract, no pending {} !
Having a member and pass the same to the base class works if:
DerrivedClass::DerrivedClass(SomeParamType* p)
: BaseClass(p),
derrivedClassMember(p),
{
...
}
... but how to share without passing it as param to the DerrivedClass constructor? Is this valid? Or is the derrivedClassMember not initialized at this time?
DerrivedClass::DerrivedClass()
: BaseClass(derrivedClassMember),
derrivedClassMember(new SomeParamType()),
{
...
}
I'm not able to change the base class implementation.
In C++11 you could use a delegating constructor:
class Derived : public Base {
public:
Derived() : Derived(new SomeParamType()) {}
...
private:
Derived(SomeParamType* p) : Base(p), derivedMember(p) {}
};
As a side note, I know this is probably just an example but you shouldn't create unmanaged objects on the heap like this in a constructor: if the Base constructor throws then you're in for a memory leak. Prefer smart pointers whenever possible.
I'm cringing as I write this, but....
DerrivedClass::DerrivedClass(SomeParamType* p = new SomeParamType())
: BaseClass(p),
derrivedClassMember(p)
{
}
I need to go shower now. Regardless, in deference to your question, yes, your base constructor should be executed before your members are initialized. Members have to be initialized in their top-down order, starting with the base members in its constructor and working out.
Note: I'd have to dust off my standard copy to find where this is specified, but I'm fairly sure its in there, as lint loves to tell you about out-of-order initialization warnings and their non-compliance.
It is not initialialized at that time. The baseclass constructor is called before the derrivedClassMember is initialized. That's because the derived members or the constructor of the derived class may depend on members of the baseclass.
To sum up the answers given up to now, and add a bit more, there are a few possible solutions.
1 If your base class has an accessor for the member, its fairly easy:
DerrivedClass::DerrivedClass()
: BaseClass(new SomeParamType()),
derrivedClassMember(getBaseClassMember()),
{
...
}
2 in C++11, use a delegating constructor, calling the original constructor you posted:
DerrivedClass::DerrivedClass()
: DerrivedClass(new SomeParamType())
{}
3 in C++03, use a default argument (which is ugly):
DerrivedClass::DerrivedClass(SomeParamType* p = new SomeParamType())
: BaseClass(p),
derrivedClassMember(p),
{
...
}
4 Another workaround, to get rid of the constructor default argument in C++03, would be to use multiple inheritance to get the derivedclassMember initialized before the base class:
struct DerivedClassInitializationWorkaround {
SomeParamType* derivedClassMember:
DerivedClassInitializationWorkaround(SomeParamType* param)
: derivedClassMember(param) {}
};
class DerivedClass : private DerivedClassInitializationWorkaround, //this has to go first!
public BaseClass {
public:
DerivedClass::DerivedClass()
: DerivedClassInitializationWorkaround(new SomeParamType())
, BaseClass(derivedClassMember)
{}
};
The initialization of base classes occurs in the order of their declaration, so if you derive from DerivedClassInitializationWorkaround, the derivedClassMember it contains gets initialized first.
In any cases, your code is not exception safe. You should not store owning pointers as raw pointers but use smart pointers. Since you can't change the base class, you will have to determine if it takes ownership of the object (i.e. if it destroys the object you pass to its constructor.
If the base class object takes ownership, you are more or less stuck with the existing solutions, except that your derived class should store a reference instead of the pointer, because the base class object and therfore the SomeParamType object will outlive the derived class' object.
If the base class does not take ownership, you should store a unique_ptr:
class DerivedClass : public BaseClass {
unique_ptr<SomeParamType> derivedClassMember;
DerivedClass::DerivedClass(unique_ptr<SomeParamType> param)
: BaseClass(param.get())
, derivedClassMember(move(param))
{}
public:
DerivedClass::DerivedClass()
: DerivedClass(make_unique<SomeParamType>)
{}
};
Short answer is no, it is not valid.
Here's a good answer to your question:
Order of calling base class constructor from derived class initialization list
I am new to C++ programming language, i have a confusion about order of calling the constructor in inheritance. my question is even though the constructor and destructor are not inherited by derived class why the base class constructor will call when i create a derived class object.
The purpose of a constructor is to define how the data members should be initialised. Since a derived class inherits the data members from the base class, any constructor of the derived class must define not only how to initialise the data members that are specific to the derived class, but also those coming from the base class.
The natural way to do this (and required by the C++ Standard) is by calling a base class constructor. If you don't include a specific constructor call in the initialization list for your derived-class constructor, the default constructor of the base class will be used to initialise the base-class members.
struct base
{
int _i; // a data member
base():_i(0) {} // default constructor
base(int i):_i(i) {} // special constructor
};
struct derived : base
{
int _j; // a data member specific to the derived class
derived(int i, int j):_j(j) {} // user-defined constructor for the derived class
};
The example above illustrates how the derived-class constructor can initialise its member _j, but the member _i, coming from the base class, must be initialised using a base-class constructor.
The way it's written above, the default constructor base::base() will be automatically called by the compiler, i.e. _i will be initialised to 0.
But you can change that behaviour by including a call to a specific constructor:
struct derived : base
{
int _j;
derived(int i, int j):base(i),_j(j) {} // user-defined constructor for the derived class
};
The order of the constructor calls is: First constructor calls of the base class, then initializers for the derived-class specific members. This is only natural because the derived class, in a sense, is an extension of the base class, and it makes sense to regard the base-class part of the derived-class object as being there first.
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.