tags:

views:

255

answers:

6

I want to ensure that the following type of call is illegal:

MyClass me;
MyClass you;
me = you; // how to make this illegal?

Is it possible?

+9  A: 

declare the assignment operator as private.

AraK
+8  A: 

Yes - define a private assignment operator (operator=) or derive from the handy boost::noncopyable class.

Rob
It's actually `boost:noncopyable` without the underscore.
FredOverflow
Oops. Cheers Fred.
Rob
+2  A: 

Use const.

MyClass const me;
MyClass you;
me = you; // compilation error
Didier Trosset
+12  A: 

Declare the assignment operator private:

class A {
   private:
     void operator=(const A&);
   ...
};

but don't provide an implementation - you will get a compile or link-time error if you try to perform an assignment to A.

I prefer to use a macro to do this. This also prevents copying, by making the copy constructor private too:

#define CANNOT_COPY( class ) \
   private:                  \
     class(const class&);    \
     void operator=(const class &) \

I can then say things like:

class A {
  CANNOT_COPY( A );
  ...
};

which is easy to read and easy to search for.

anon
usually, the copy ctor should also be disabled to avoid `MyClass me = you;` case.
Nick D
BeeBand
@BeeBand You should always prefer to pass by const reference. And if you really need to pass by value, you probably need to assign as well.
anon
@Neil. Ah ok I get it now. Thanks!
BeeBand
@Niel, macro???
Kornel Kisielewicz
@Kornel Sure - I have a few utility macros I use in all my code. The alternative to this one is either to write the code out each time or use inheritence as in boost::no_copy. I think inheritence should definitely be the tool of last resort, so I use a macro.
anon
Should have been boost::noncopyable, of course.
anon
@Neil Why do you want to avoid inheritance ?
Benoît
@Benoit I only use inheritence when I want polymorphism - that's what it's for. Using it for other reasons (like implementation) opens all sorts of cans of worms and possibilities of misuse, accidental or otherwise, by users of my code.
anon
Then you're no friend of (inheritance-based) mixins? Or would that be an exception for you?
Georg Fritzsche
@gf Not a great fan, no. I'm not against MI, however.
anon
Let me state my position clearly: If there are two ways of doing something, one which uses inheritance, and one which does not, and if both take about the same effort, choose the one that does not.
anon
@Neil: Protected and Private inheritance have nothing to do with polymorphism.
Joe Gauterin
@Joe Which bit of my comment immediately above yours did you not understand?
anon
Just to enlighten a webdeveloper who has not much idea about c++: when would one use this feature in order to prevent object assignment?
Max
@Max You might want to make this a separate question, but ... almost always. Consider a BankAccount class. Most banks will be very unhappy if one account can be assigned to another, or if copies of accounts can be taken and operated on independently.
anon
@Neil: The bit where you just restated your beliefs without providing any justification - especially the bit where you state that all inheritance (not just public) "opens all sorts of cans of worms and possibilities of misuse, accidental or otherwise, by users of my code."
Joe Gauterin
+1  A: 

I use to derive my noncopyable classes from a common noncopyable class. If not using boost, I usually use this shortcut:

class NonCopyable
{
protected:
    /**
     * Protected default constructor
     */
    NonCopyable() {}

    /**
     * Protected destructor
     */
    ~NonCopyable() {}

private:

    /**
     * Private copy constructor
     */
    NonCopyable( const NonCopyable& );

    /**
     * Private assignment operator
     */
    const NonCopyable& operator=( const NonCopyable& );
};

Note that neither the copy constructor nor the assignment operators have an implementation.

Kornel Kisielewicz
A: 

The other answers here are all correct. However, it is important to note that you are only prohibiting the specific code you mentioned. Someone can still come along and make a duplicate of your class by using memcpy or other strategies.

David Pfeffer
Only by invoking undefined behaviour.
anon