I frequently run into the problem, that I must extend a compiler generated copy constructor. Example:
class xyz; class C { ... int a, b, c; std::set<int> mySet; xyz *some_private_ptr; };
Assume, that some_private_ptr
should only be copied under certain conditions. For other conditions it should be reset to NULL
on copy. So I have to write a copy constructor like:
C::C(const C &other) : a(other.a), b(other.b), c(other.c), mySet(other.mySet) { if(CanCopy(other.some_private_ptr)) // matches condition some_private_ptr = other.some_private_ptr; else some_private_ptr = NULL; }
The problem is that the class might have a number of data members, and that I very likely may forget to update the copy constructor when I add a data member. It would be very nice if I just could write.
C::C(const C &other) : C::default_copy(other) { if(CanCopy(other.some_private_ptr)) // matches condition some_private_ptr = other.some_private_ptr; else some_private_ptr = NULL; }
This would make my code more safe and easier to maintain. Unfortunately I don't know of such a possibility. Is there any?
Constructors can be overloaded in a similar way as function overloading. Overloaded constructors have the same name (name of the class) but the different number of arguments. Depending upon the number and type of arguments passed, the corresponding constructor is called.
The compiler also creates a copy constructor if we don't write our own copy constructor. Unlike the default constructor, the body of the copy constructor created by the compiler is not empty, it copies all data members of the passed object to the object which is being created.
In C++, the compiler automatically generates the default constructor, copy constructor, copy-assignment operator, and destructor for a type if it does not declare its own. These functions are known as the special member functions, and they are what make simple user-defined types in C++ behave like structures do in C.
how many times a copy-constructor is called, according to me its 5 but answer is 7.
The easiest way is to introduce a base class:
class xyz; struct CDetail { //... int a, b, c; std::set<int> mySet; xyz *some_private_ptr; }; struct C : private CDetail { C(C const &other) : CDetail(other) { if (!CanCopy(other.some_private_ptr)) some_private_ptr = 0; // opposite case already handled } };
This is an abuse of inheritance to an extent, but the advantages over a nested "impl" class are 1) you can access each member as "name" rather than "data.name" (reducing code changes when refactoring), and 2) (though only sometimes desired) you can "promote" individual members to protected or public without affecting other members:
struct C : private CDetail { protected: using CDetail::a; }; struct D : C { void f() { cout << a; } }; int main() { D d; d.f(); // D can access 'a' cout << d.a; // main cannot access 'a' return 0; }
the moment you define your own copy ctor, the compiler does not bother generating one for you. Unfortunately this means you have to do all the leg work yourself! You could group the members into some sort of impl_
structure within your class, and then rely on the copy ctor for that.
for example:
class xyz; class C { struct impl_ { int a, b, c; std::set<int> mySet; xyz *some_private_ptr; }; impl_ data; };
now in your copy ctor
C::C(const C &other) : data(other.data) { // specific stuff... }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With