How to copy a class in C++? - 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;
};

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()) {}

Delegating to a default C++ constructor

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

Copy constructor calling copy constructor of another class

I was wondering, can I and if I do, how to call a copy constructor of template class A in copy constructor of class B, both class are not in the same file.
template<typename T> class A: public AP<T>
{
public:
A();
A(const A&);
~A();
};
#include "A"
class B: public BP
{
private:
A<int> Amember;
public:
B();
B(const B&);
~B();
};
Thanks :)
If I understand the question, I think you're after the optional initializer list in the constructor of your B class. Doesn't matter if you want to call the default constructor or copy constructor. In the definition of the constructor, you can put a colon and the list of how each member variable should be initialized. i.e., which constructor should be called.
#include <iostream>
using namespace std;
class A{
public:
A(){cout<<__PRETTY_FUNCTION__<<endl;}
A(int i){cout<<__PRETTY_FUNCTION__<<" "<<i<<endl; data = i;}
A(const A& a){cout<<__PRETTY_FUNCTION__<<endl; data = a.data;}
private:
int data;
};
class B{
public:
B() : a(){}
B(int i) : a(i){}
B(const B& b) : a(b.a) {}
private:
A a;
};
int main(){
B b1; // default constructor
B b2(5); // integer constructor
B b3(b2); // copy constructor
}

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

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.