Call C++ constructor of base class with same arguments - c++

I've ve something like this:
class A {
public:
A(int a1,int a2,int a3) {
}
}
class B: public A {
public:
B(int a1,int a2,int a3) : A(a1,a2,a3) {
.. Do Some More Init for B ...
}
}
Is it possible to write the constructor in a a shorter form?
The Constructor of the base class should be called with the same arguments. But I don't want to list all of the arguments explicit. And I need to do some special initialization stuff for class B.
I think something like this:
class B: public A {
public:
B(int a1,int a2,int a3) : A(...AUTOARG...) {
.. Do Some More Init for B ...
}
}
Is this possible in C++/11?

If there is no code happening inside B's constructor and you simply want to allow its construction in the same ways A is constructible, you can inherit A's constructors:
class B: public A {
public:
using A::A;
};
This will give B all the same constructors as A has.
If, as the edited question says, B's constructor is not empty, you can still get "do all A does plus some more" in a generic (but not as nice) way using a "catch-all" constructor with perfect forwarding:
class B: public A {
public:
template <class... Arg>
B(Arg&&... arg) : A(std::forward<Arg>(arg)...) {
//.. Do Some More Init for B ...
}
}
Note that this changes B's behaviour slightly with respect to type traits. It now seems constructible from anything, but using incorrect arguments will fail to compile. If you also need the class to play nice with constructibility detection traits etc., you can conditionally disable the incorrect instantiations using SFINAE.

Better still, inherit the constructor. This is a new feature from C++11:
class B: public A {
public:
using A::A;
};
Unfortunately though, if you want the B constructor to do additional things, then you'll need to write it out longhand as you currently do.

Related

Two members, default initialized in Base, possibly non-default initialized in Derived

I have a base class with a default constructor.
class Base
{
public:
Base();
private:
Type1 m_ofType1;
Type2 m_ofType2;
}
Base::Base()
: m_ofType1(defaultExpr1)
, m_ofType2(defaultExpr2)
{
}
And I have a derived class, which may be:
default constructed, with m_ofType1 and m_ofType2 being initialized by their respective default expressions,
provided with a Type1 only, or
provided with a Type2 only.
class Derived : public base
{
public:
Derived(); // m_ofType1 and m_ofType2 will be initialized with their default expressions.
Derived(Type1 overrideOfType1); // m_ofType1 will be initialized with overrideOfType1 and m_ofType2 will be initialized with its default expression.
Derived(Type2 overrideOfType2); // m_ofType1 will be initialized with its default expression and m_ofType2 will be initialized with overrideOfType2.
}
Base is for Production code and Derived is for test code. I would like to implement the constructors without data or code duplication, but I can't see how.
Given the constraints, which I hope have been made clear, do you all know how to implement the above constructors without data or code duplication?
Example of code duplication:
We could add protected constructors to base:
Base(Type1);
Base(Type2);
That means that the Derived constructors would just forward the call to their respective Base constructors.
Derrived::Derrived()
: Base()
{
}
Derived::Derived(Type1 overrideOfType1)
: Base(overrideOfType1)
{
}
Derived::Derived(Type1 overrideOfType2)
: Base(overrideOfType2)
{
}
In doing this, the question changes a little. How do you implement the Base constructors without data or code duplication.
Here's my best attempt at doing this. It doesn't work, and I'll show you why.
First, add another constructor to Base:
Base(Type1 ofType1, Type2 ofType2);
Base::Base()
: Base(defaultExpr1, defaultExpr2)
{
}
Base::Base(Type1 overrideOfType1)
: Base(overrideOfType1, defaultExpr2)
{
}
Base::Base(Type2 overrideOfType2)
: Base(defaultExpr1, overrideOfType2)
{
}
Base::Base(Type1 ofType1, Type1 ofType2)
: m_ofType1(ofType1)
, m_ofType2(ofType2)
{
}
You can see that defaultExpr1 and defaultExpr2 have been duplicated.
I think the Derived is close to being a red herring. Basically you are asking for 3 ways to construct a Base and to do that it is Base that has to provide appropriate constructors, something along the line of:
struct Base {
Type1 m_ofType1{defaultExpr1};
Type2 m_ofType2{defaultExpr2};
Base() = default;
Base(Type1 x) : m_ofType1(x) {}
Base(Type2 x) : m_ofType2(x) {}
};
Default initializers (defaultExpr1 and defaultExpr2) can be overriden by initializers in the constructors initializer list.
Now add access restrictions and derived classes calling those constructor as you wish (perhaps making the last two protected and data members private). To stay with your example that would be
struct Derived : Base {
Derived(Type1 x) : Base(x) {}
Derived(Type2 x) : Base(x) {}
};
I doubt you can get it any shorter than this.
You can pass the arguments to private members 1 & 2 with a protected constructor. This will keep those members shielded without giving the derived classes full access to them.
class Base
{
private:
Base();
protected:
Base(Type1 overrideOfType1, Type2 overrideOfType2) { }
private:
Type1 m_ofType1;
Type2 m_ofType2;
};
class Derived : public Base
{
public:
Derived() : Base(Type1{}, Type2{}) { }
Derived(Type1 overrideOfType1) : Base(overrideOfType1, Type2{}) { }
Derived(Type2 overrideOfType2) : Base(Type1{}, overrideOfType2) { }
};
Oh, and by the way, members are initialized with the default constructor if they have one automatically, so you don't need to be explicit for the empty base constructor. For instance, if the default constructor of Base was accessible, you could just define:
Base::Base() = default;
And the members would have their default values.

Do we "inherit" constructors in C++ ? What's is exact definition of "inheriting"

I wonder why people say:
"Inheriting class doesn't inherit the constructor".
If you could CAN use the parent class' constructor, and the parameterless constructor are called automatically no matter what.
Example:
#include <iostream>
using namespace std;
class A {
private :
int x;
public :
A () {
cout << "I anyway use parameter-less constructors, they are called always" << endl;
}
A (const int& x) {
this->x = x;
cout << "I can use the parent constructor" << endl;
}
};
class B : public A {
private :
int y;
public :
B() {
}
B (const int& x, const int& y) : A (x) {
this->y = y;
}
};
int main() {
B* b = new B(1,2);
B* b1 = new B();
return 0;
}
http://ideone.com/e.js/6jzkiP
So is it correct to 'say', constructors are inherited in c++ ? What is exact definition of "inherit" in programming languages ?
Thanks in advance.
I wonder why people say: "Inheriting class doesn't inherit the constructor".
Perhaps it is best to illustrate this with an example:
struct Foo
{
Foo(int, int) {}
};
struct Bar : Foo
{
};
What it means is that there is no Bar::Bar(int, int) constructor that you can call, despite the existence of a constructor with the same parameter list in the base class. So you cannot do this:
Bar b(42, 42);
In C++11, you can actually inherit constructors, but you must be explicit about it:
struct Bar : Foo
{
using Foo::Foo;
};
Now, you can say Bar b(42, 42);
What they mean is that constructor signatures are not inherited.
In your example, B does not have a constructor taking a single const int& even though its base class does. In this sense it has not "inherited" the constructor (but can still make use of it).
I think what they mean is:
struct A {
A(int, int) { }
};
struct B : public A {
};
int main()
{
A a(1, 2); // ok
B b(1, 2); // error
}
To compare with “non-special” member functions:
struct A {
void f() { }
};
struct B : public A {
};
int main()
{
A a;
B b;
a.f(); // ok
b.f(); // ok too
}
But of course, from within B you can call accessible A constructors (as automatically generated ones do). Ditto for the destructor.
Note that in C++11 you can use the “inheriting constructors” feature:
struct A {
A(int, int) { }
};
struct B : public A {
using A::A;
};
int main()
{
A a(1, 2); // ok
B b(1, 2); // ok now
}
A derived class can/must see base class constructors in order to invoke them, for consistency. However, their signature is not exposed in the derived class, hence, one cannot construct the class without an explicitly defined constructor, which forwards the required arguments to the base class constructor.
In C++11, one can inherit constructors: What is constructor inheritance?
Another approach to circumvent 'proxy constructors' in C++ < 11: How to define different types for the same class in C++
In your example, the default ("parameterless" as you say) constructor of B does invoke the default constructor of A, but this does not mean that B "inherited" that constructor, only that it "has access to" it. That is, A's default constructor is accessible from within B, yet it is not accessible from outside (no one can use A's default constructor from outside to construct an instance of B).
Another way to look at it is to ask, what is something frustrating about constructors and inheritance in C++? A common answer from some people (including myself) would be that there is no automatic facility which allows "pass-through" construction of base classes taking arguments from derived class constructors without explicitly declaring and defining the latter.

C++ no appropriate default constructor available - inherited templated constructor w/ no arguments

I've looked at over a dozen qst's with the phrase no appropriate default constructor available in it but none help with my own problem.
It's a very basic C++ qst (as I'm still learning the ropes), so sorry in advance if your eyes are glazing over at it's simplicity. I am trying to inherit a class that has a templated constructor with no arguments. Such as:
class Base {
public:
template<class T>
Base() {
T *t = this;
//more irrelevant stuff
}
}
I've tried
class Derived : public Base {
public:
Derived() : Base() {
}
}
and
class Derived : public Base {
public:
Derived() {
}
}
to no avail. In both cases I get the error message no appropriate default constructor available . How to go about doing this? If this is not possible can you explain why?
It worked when I set up my constructor like template<class T> Base(T *t) (taking the template argument as a parameter).
p.s. In case it matters, in my code I am also inheriting Derived by another class.
there is no syntax for accessing the default constructor in
class blah_t
{
public:
template< class other_t > blah_t() {}
};
there also some other ways to make the default constructor inaccessible, e.g.
class blah_t
{
public:
blah_t() {}
blah_t( int = 666 ) {}
};
as the holy standard explains it, constructors don't have names…
but, back to the original question, in order to be able to specify the template argument, you need some ordinary function argument that involves the template parameter type

C++ casting to derived and parent structs

I was wondering how to do something in C++. I want to be able to create an instance of this struct
struct ComplexInstruction : simple_instr
{
bool isHead;
bool isTail;
};
that copies all the data from the simple_instr instance. So essentially, I want to do something like this
ComplexInstruction cInstr = instr; // <- instance of simple_instr
and have cInstr have a copy of all the data in instr without having to copy over every field (since there's alot of them). I'm not sure how do this, and I don't think simple casting will work. Additionally, is it possible to do the reverse? I.e. have an instance of ComplexInstruction and turn it into an instance of simple_instr. I assume this can be done using casting, but I don;t have alot of experience with c++
Thanks in advance
Create a consctructor in the derived class to initialize from a base class.
class Base
{
int x;
public:
Base(int a) : x(a){}
};
class Derived : public Base
{
public:
Derived(const Base & B) : Base(B){}
};
Note that if you have a derived object of Base, you actually have a base object and you can safely use the base copy ctor like so.
Derived d;
Base b(d);//the parts of Base that are in Derived are now copied from d to b.
//Rest is ignored.
If you want to be more verbose, you write an operator= in your derived class like
void operator=(const Base & b)
{
Base::operator=(b);
//don't forget to initialize the rest of the derived members after this, though.
}
It all depends on what you want to do, really. The important thing is: be explicit. Don't leave uninitialized members of your class.
You need to provide a constructor that takes an argument that is convertible to const simple_instr&:
struct simple_instr {
int i;
simple_instr(): i(0) { }
explicit simple_instr(int i): i(i) { }
};
struct ComplexInstruction: simple_instr {
explicit ComplexInstruction(const simple_instr& simple):
simple_instr(simple), isHead(false), isTail(false) { }
bool isHead;
bool isTail;
};
int main() {
simple_instr instr;
ComplexInstruction cInstr(instr);
}
Here I chose an explicit constructor, but depending on the semantics, an implicit one could also be appropriate. Only if the constructor is implicit, the =-style initialization works without casting.
Edit: This is not the best way to accomplish this, please look at the other answers.
This will do what you are looking for.
struct ComplexInstruction : simple_instr
{
ComplexInstruction(const simple_instr &simple)
{
*((simple_instr*)this) = simple;
}
bool isHead;
bool isTail;
};
Then ComplexInstruciton complex = simple; will call the conversion constructor. ComplexInstruction's copy construct casts this to its base class and the = will call simple_instr's copy constructor, which by default is a bitwise copy.

Injecting code in a C++ base class constructor

I'm deriving a class which is available from a C++ library, and the constructor of my subclass will only work properly when I execute some code before the base class constructor gets called. (Yes, I know, bad design, but I cannot influence how the library which I'm using works.)
If the base class constructor takes arguments, doing this is actually quite simple:
struct A {
A(bool a) { printf("A::A()\n"); }
};
bool inject(bool a) { printf("inject()\n"); return a; }
struct B : public A {
B(bool a) : A(inject(a)) { printf("B::B()\n"); }
};
Now, when I construct an instance of B, inject() gets called before A::A(). But is there a way to do this when the base class ctor has no arguments?
You have a case of "Base from member initialization".
A solution is there.
Hacky injection code aside, I think the reasonable way to do this is to do the "has a" instead of "is a" pattern: Simply have an instance of the library class inside of your own class. That way you can control allocation and deallocation order to your heart's content.
Your solution for the one parameter constructor doesn;t really seem useful in the sense that it still cannot access the class being constructed (as it doesn't happen yet) and it is unclear how anything useful can be done with this hacky form (except perhaps setting global scope values which affect the base ctor).
Stephan's proposed solution would look something like this:
struct A {
A() { printf("A::A()\n"); }
};
struct Injector {
Injector() { printf("inject()\n"); }
}
struct B : public A,private Injector {
B() : Injector(), A() { printf("B::B()\n"); }
};
This is an okay solution but seems a little clumsy to me.
Another possible solution is using static class function in place of the constructor for B which run the inject before returning an instantiated object created with a private constructor but it seems from your question that this don't suit your context.
Why you can't add one more layer ?
struct A {
A(bool a) { printf("A::A()\n"); }
A();
};
struct A_Wrap : public A {
A_Wrap(bool ) : A() { } ;
};
bool inject(bool a) { printf("inject()\n"); return a; }
struct B : public A_Wrap {
B(bool a) : A_Wrap(inject(a)) { printf("B::B()\n"); }
};