Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I extend a compiler generated copy constructor

Tags:

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?

like image 914
RED SOFT ADAIR Avatar asked Jan 31 '11 16:01

RED SOFT ADAIR


People also ask

Can we overload copy constructor?

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.

What does compiler generated copy constructor do?

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.

Is copy constructor is automatically created by compiler?

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 copy constructor will be invoked?

how many times a copy-constructor is called, according to me its 5 but answer is 7.


2 Answers

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; } 
like image 174
Fred Nurk Avatar answered Nov 05 '22 19:11

Fred Nurk


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...       } 
like image 36
Nim Avatar answered Nov 05 '22 18:11

Nim