Maroun
Maroun

Reputation: 95968

Disallowing class copying in C++

When I want to disallow class copy in C++, I usually declare a private operator= and a copy constructor and I don't implement them:

class MyClass
{
  char* _str;
  int _len;
  MyClass(const MyClass& rhs);            //No implementation
  MyClass& operator=(const MyClass& rhs); //No implementation
public:
  MyClass();
  MyClass(const char *);
}

Is this considered a bad style? Is there another way to do this?

Upvotes: 3

Views: 577

Answers (3)

BЈовић
BЈовић

Reputation: 64223

There are two ways, and both would cause a compilation errors :

C++11 way:

class MyClass
{
  char* _str;
  int _len;
  MyClass(const MyClass& rhs) = delete;
  MyClass& operator=(const MyClass& rhs) = delete;
public:
  MyClass();
  MyClass(const char *);
};

C++03 way:

class MyClass
{
  char* _str;
  int _len;
public:
  MyClass();
  MyClass(const char *);

  MyClass(const MyClass& rhs);            //No implementation
  MyClass& operator=(const MyClass& rhs); //No implementation
}

If you just declare copy constructors public, you'll get linker errors, but the compilation will pass. Since the compilation happens before linking, breaking the compilation is better, because you'll catch the errors sooner.

Upvotes: 2

Björn Pollex
Björn Pollex

Reputation: 76808

In C++11 you can explicitly delete these functions (which is preferred over omitting the implementation, because it is more readable, and it will always generate a compiler-error, and not just a linker-error):

class MyClass
{
  char* _str;
  int _len;
  MyClass(const MyClass& rhs) = delete;
  MyClass& operator=(const MyClass& rhs) = delete;
public:
  MyClass();
  MyClass(const char *);
}

In C++03 you can use a base-class such as boost::noncopyable to achieve the same effect. This might be more readable (this is essentially the same approach as yours - this base-class has private copy-constructor and assignment-operator, so inheriting from it will make your class uncopyable):

class MyClass : boost::noncopyable
{
  char* _str;
  int _len;
public:
  MyClass();
  MyClass(const char *);
}

The difference between shallow and deep copying in C++ rests entirely in how you implement your copy-constructor (because your assignment operator should be implemented using your copy-constructor). If you don't have one, neither shallow nor deep copying is possible, if you have, it depends on how it is implemented.

Upvotes: 10

Mr.C64
Mr.C64

Reputation: 42944

You can create a preprocessor macro to achieve the same thing, e.g.

#define DISABLE_COPY_AND_ASSIGN(className) private: \
    className(const className&); \
    className& operator=(const className&);

and then use it like this:

class MyClass
{
   DISABLE_COPY_AND_ASSIGN(MyClass)
public:
   ....
};

You can derive from boost::noncopyable as well:

class MyClass : boost::noncopyable
{
public:
   ....
};

Moreover, in C++11, you can use = delete:

MyClass(const MyClass&) = delete;
MyClass& operator=(const MyClass&) = delete;

Upvotes: 3

Related Questions