Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why would I make copy constructor and assignment operator private and implemented in C++?

Inspired by this question.

Usually the reason to make copy-constructor and assignment operator private is to make the class non-copyable so that objects can only be created and destroyed, but not copied - most of the times it is because copying them would make no sense. In such cases the copy constructor and the assignment operator are both made private and not implemented - if the class is not copyable then noone should copy.

Is there a case when copy constructor and assignment operator need to be private and have meaningful implementation at the same time?

like image 724
sharptooth Avatar asked Jul 25 '11 11:07

sharptooth


3 Answers

There are two cases that come to mind immediately:

  1. friends:

    Say that, as part of your design, you have two highly coupled classes where one needs to be able to copy the other (say, as in a factory model or some such), but you don't want to let the whole world be able to copy it.

  2. wrappers:

    Say you want to be able to conditionally clone some element, depending on some internal behavior (e.g., depending on some class-stateful condition) - the cleanest way, from a language perspective - is still to separate the copying into its own function. This would allow for good separation of concerns.

like image 118
Nate Avatar answered Nov 11 '22 09:11

Nate


My guess is that this can be useful for a class that is holding a list of itself - then it can copy the instances internally. This is really only useful for a class that is both the item and the container:

class MyItems
{
private:
    /* Copy ctor and =operator */
    List list;
public:
    void AddItems(MyItems* items)
    {
        MyItems* added = new MyItems(items);
        list.Add(added);
    }
};

Another thought is to allow cloning in circumstance controlled by the class. This might be useful when copying can make sense, but only on specific conditions or permissions:

class MyClass
{
private:
    /* Copy ctor and =operator */
public:
    MyClass* clone()
    {
        if (canClone)
        {
            MyClass* cloned = new MyClass(this);
            return cloned;
        }
        else
        {
            return NULL;
        }
    }
};
like image 44
Eli Iser Avatar answered Nov 11 '22 10:11

Eli Iser


  1. We make copy constructor and operator = unimplemented so that even a friend cannot have any access to it. If you implement, it means you want a friend to have access. This is a design decision.
  2. You want to do explicit cloning; i.e. allow copying but also make its code "dirty" looking (something like C++ style casting operations, which shows dirt in your code)

e.g.

class A {
  A(const A& obj) { ... }
  A& operator = (const A& obj) { ... }
public:
  A& clone(const A& obj)
  {
    *this = obj;
    return *this;
  }
};

We have put this wrapper clone() to allow the user for cloning, however it also displays explicitly what exactly he/she is doing.

like image 39
iammilind Avatar answered Nov 11 '22 10:11

iammilind