سؤال

I have a long class with a lot of data members. I want to write a copy constructor for it. But, if I write my own copy constructor, I lose access to the default copy constructor.

I just want to repair a few pointers in my own copy constructor. So I want to have a shallow copy of the object which can be done by the default copy constructor.

Is there a possibility to access the default copy constructor when I have my own copy constructor?

هل كانت مفيدة؟

المحلول

Wrap the things you don't want to change in a struct, and derive (privately) from it. In your copy constructor, simply invoke the copy constructor of your base class.

نصائح أخرى

No you cannot have both default and your own copy c-tor.

But there are two workarounds with this problem:


1 Enclose your pointers in some class with defined copy semantics

Example:

class A {
public:
private:
   int trivial1;
   int trivial2;
   ...
   SomePointer  nontrivialMember;
};

class SomePointer {
public:
  SomePointer(const SomePointer&); // here the non trivial part of A copy semantics
  int* nonTrivialMember;
};

2 Enclose the trivial parameters in some trivial structure

Example:

class A {
public:
   A(const A& o) : data(o.data) {
     // non trivial part
   }
private:
   struct Data {
     int trivial1;
     int trivial2;
     ...
   } data;
   int* nontrivialMember;
};

I would always select the first solution.

[UPDATE]

There is also 3rd solution, very similar to my second, enclose your trivial part in privately inherited base class. I'd still prefer the 1st solution.

The simplest approach to this would be to wrap up the pointers into classes that will perform the 'repair' manually in their copy constructor, then you can happily use the default copy constructor.

No, there is no way to call the default copy constructor from an user defined copy constructor.

You can either use the default or your own, not both. If you want to choose different functionality for different objects you should just write a member function that handles that case.

void DeepCopy(MyClass* rhs);

For example.

You cannot access default copy ctor if you created your own - compiler just doesn't generate it. But ther is workaround - split you class into data structure and logic.

See example:

struct Data
{
  int i;
  std::string s;

  Data(): i(), s() {}
};

class Code: private Data
{
public:

  Code() {}

  Code(const Code& rhs): Data(rhs) // Call default copy ctor
  {
     i = 42; // Your copy part
     return *this;
  }

};

My solution is a simple memcpy() instead of the impossible call to the implicit (compiler generated) copy constructor, as the example shown below:

Class Foo
{
public:
   ...
   Foo (Foo & other) {
      // copies trivial part (and non-trivial part with possible wrong values)
      memcpy(this, &other, sizeof(Foo));

      // your non-trivial part here, overwrites the wrong values (if any) above.
   }
}

Yet the side-effect is that the memcpy() will also copy those non-trivial part, which is a waste. If the non-trivial part does not contain too much space, I will prefer my solution.

For example, a class like below wastes only 4 byte copy of the one pointer, assuming the size of a pointer is 4 bytes.

Class Bar
{
    int x, y, z;

    // memcpy() wastes these 4 bytes copy,
    // since actual copy constructor wants a new string
    string *s;  
}

This worked for me... (C++11, don't know if it works on older std) Not sure why it doesn't end up in an endless loop.

class Foo {
public:
  Foo(const Foo &orig) {
     *this = orig;
     ... exchange pointers, do own stuff
  }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top