Delegating to a default C++ constructor - c++

Assume a C++ class A with members that can all be copied by the their respective copy constructors. We can rely on the default copy constructor for A to copy its members:
class A {
private:
A(const A&) = default; // We don't really need this line
int a;
B b;
double c;
}
But now let's assume that I want to "extend" (or annotate) the default constructor of A so that in addition to copying its members, it does something else, e.g. writes a line to a log file.
I.e. I'd like to write something like:
class A {
public:
A(const A& a) : A::default(A) {
print("Constructing A\n");
}
private:
// like before
}
Unfortunately that is not correct C++ syntax.
So is there a syntax which allows delegating to a default C++ constructor while explicitly defining the same constructor?

The simplest is to move all members into a base class and write the message in a derived class:
class A_helper {
private:
int a;
B b;
double c;
};
class A : public A_helper {
public:
A() = default;
A(const A& a) : A_helper(a) {
print("Constructing A\n");
}
A(A&& a) : A_helper(std::move(a)) {
print("Constructing A\n");
}
};

You can delegate to the default constructor like you would default-initialize a member variable:
A(const A&) : A()
{
...
}

As often, "We can solve any problem by introducing an extra level of indirection." ( "…except for the problem of too many levels of indirection,"):
struct VerboseA
{
VerboseA() = default;
VerboseA(const VerboseA&) { print("Constructing A\n"); }
VerboseA(VerboseA&&) { print("Constructing A\n"); }
};
And then
class A : VerboseA // EBO (Empty Base Optimisation)
{
private:
A(const A&) = default; // We don't really need this line
int a;
B b;
double c;
};
or in C++20
class A {
private:
A(const A&) = default; // We don't really need this line
[[no_unique_address]]VerboseA verbose; // "EBO" equivalent with attribute
int a;
B b;
double c;
};

Related

Constructor inheritance behaving weirdly

In the following situation:
class A
{
protected:
int m_int;
A() : m_int{-2} {};
public:
A(const A& a) { m_int = a.get(); }
A& operator=(const A& a) { m_int = a.get(); return *this; }
int get() const { return m_int; }
};
class B : public A
{
protected:
using A::m_int;
public:
// same constructors as parent, but public
using A::A;
};
class C : public B
{
public:
// same constructors as parent
using B::B;
C(int x) { m_int = x; }
C(const B& b) { C(b.get()); }
};
class D : public C
{
public:
// same constructors as parent
using C::C;
D(const B& b) { D(b.get()); }
};
int main()
{
C c(5);
D d(c);
return d.get();
}
I would expect for main() to return 5. Instead, it returns -2. It seems it's calling the default constructor of A, whereas I would have expected for it to call the D(const B& b) constructor. What's going on?
Why do I need to provide an explicit constructor for C(const B& b)? I would have guessed for a default behavior to be deduced, for inheritance reasons. What am I missing?
The problem is the constructor in D:
D(const B& b) { D(b.get()); }
This will be the constructor that is called. And it doesn't copy the value from b, instead it creates a new and temporary D object which is promptly destructed as the constructor function exit.
You have the same problem in the corresponding C constructor:
C(const B& b) { C(b.get()); }
You should use a constructor initializer list to delegate to the correct constructor:
D(const B& b) : C(b.get()) {}

How to copy a class in C++?

Suppose I have class A
class A{
public:
A(const A&) {};
A() {};
~A() {};
bool bln;
B b;
}
If I write
A *a2;
a2 = new A(*a);
where a is an A object, then a2->b seems different to a->b.
How can I exactly copy a to a2?
bln is not being initialized in any of A's constructors. b is only being default constructed in both constructors, and is not being copied at all in the copy constructor.
Try this:
class A
{
public:
bool bln;
B b;
A() : bln(false) {}
A(const A &src) : bln(src.bln), b(src.b) {}
};
A better option is to simply let the compiler generate a default copy constructor for you, which will effectively be the same as above:
class A
{
public:
bool bln;
B b;
A() : bln(false) {}
};
Or, in C++11 and later, you can do use:
class A
{
public:
bool bln = false;
B b;
// these are optional in this case and can be omitted
A() = default;
A(const A&) = default;
};

Simple copy constructor in C++

Let's say we have two classes in C++:
Class A{
public:
A();
private:
int k;
};
Class B{
public:
B();
private:
A a;
};
I edit my question such that it is more helpful for anyone does reach it someday.
How could I write the copy ctor of B (is it a copy ctor indeed?) for initializing a (which is of type Class A) with another object instance of A (let it be a_inst) which have already been defined and initialized before?
In other words, what would be the code for the ctor B()?
I would do it like this
B(const A &paramA) : a(paramA) {}
B(A &&paramA) : a(move(paramA)) {}
B(const B &src) : a(src.a) {}
Beside the copy constructor I am also proposing two additional constructors, one that can be initialized by l-value instances of A and other for r-value instances. Depending on the semantics of A you may not need the move version.
Class A{
public:
A();
A(const A& obj);
private:
int k;
};
Class B{
public:
B();
B(const B& obj)
: a(obj.a) { }
B(const A& obj)
: a(obj) { }
private:
A a;
};

Is it valid to copy an inherited member in the derived class constructor?

In the below code I have defined an explicit copy constructor in the derived class. I have also written my own copy constructor in the base class.
Primer says that the derived copy constructor must call the base one explicitly and that inherited members should be copied by the base class copy constructor only, but I copied the inherited members in the derived class copy constructor and it is working fine. How is this possible?
Also how do I explicitly call the base class copy constructor inside the derived class copy constructor? Primer says base(object), but I am confused how the syntax differentiates between normal constructor call and copy constructor call.
Thanks in advance.
#include<stdafx.h>
#include<iostream>
using namespace std;
class A
{
public:
int a;
A()
{
a = 7;
}
A(int m): a(m)
{
}
};
class B : public A
{
public:
int b;
B()
{
b = 9;
}
B(int m, int n): A(m), b(n)
{
}
B(B& x)
{
a = x.a;
b = x.b;
}
void show()
{
cout << a << "\t" << b << endl;
}
};
int main()
{
B x;
x = B(50, 100);
B y(x);
y.show();
return 0;
}
copy constructor is when you have another Object passed to your constructor:
class A() {
private:
int a;
public:
//this is an empty constructor (or default constructor)
A() : a(0) {};
//this is a constructor with parameters
A(const int& anotherInt) : a(anotherInt) {};
//this is a copy constructor
A(const A& anotherObj) : a(anotherObj.a) {};
}
for a derived class
class B : public A {
private:
int b;
public:
//this is the default constructor
B() : A(), b() {};
//equivalent to this one
B() {};
//this is a constructor with parameters
// note that A is initialized through the class A.
B(const int& pa, const int& pb) : A(pa), b(pb) {}
//for the copy constructor
B(const B& ob) : A(ob), b(ob.b) {}
}
How somebody else wrote here:
How to call base class copy constructor from a derived class copy constructor?
I would write the copy constructor like this instead how it was written by macmac:
B(const B& x) : A(x) , b(x.b)
{
}
To call the copy constructor of the base A you simply call it passing the derived B object A(B), is not neccessary to specify B.a.
EDIT: macmac edited his answere in the correct way, now his answere is better then mine.

Add a conversion constructor without touching class

I have two classes, from two different libraries, with the same meaning:
class A {
public:
A() {}
A(const A&) {}
};
class B {
public:
B() {}
B(const B&) {}
};
I want to call functions with B as parameter, passing an A object:
void setB(const B&) {
}
int main(int argc, char* argv[]) {
A a;
setB(a);
}
I know this is possible, adding a conversion contructor from:
class B {
public:
B() {}
B(const B&) {}
B(const A&) {} // CANNOT ADD THIS!
};
But these classes are defined in two external libraries and I haven't rights to change them.
How can I add a conversion constructor (or achieve the same result) without touching the B class definition?
How can I add a conversion constructor (or achieve the same result) without touching the B class?definition?
If the B class has a virtual destructor, you can specialize B and add the extra functionality in the specialization. If it does not have a virtual destructor, you can embed B in a wrapper class.
That means either:
class SpecialB: public B { // if B has virtual destructor
public:
SpecialB(const A&); // you _can_ do this
};
or:
class SpecialB {
public:
SpecialB(const A&); // you _can_ do this
private:
B wrapped_b;
};
Just use a factory:
struct AfromB
{
static A convert(const B&);
}
and:
setB(AfromB::convert(a));
If you have no access to B class definition, maybe the simpler is to have a void setB(const A&) overload.