Disallowing class copying in C++ - 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?

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.

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;

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.

Related

How to prevent object=constructor(); assignment in c++

This is what I am trying to do:
class A{
public:
A(){/*need to initialize something here*/}
};
int main(){
A a; //OK
a=A(); //not OK
a=A(b); //not OK
///Only A a; needs to be allowed.
return 0;
}
I need to initialize something while preventing object initialization with copy constructor and also prevent assignment to existing object.
Note: It would be good if I can do this without >=C++11.
Since C++11, just delete assignment operator:
class A{
public:
A(){/*need to initialize something here*/}
A& operator =(const A&) = delete;
};
You can achieve your goal by declaring the assignment operator and the copy constructor in the private part, and not defining them.
For example:
class A {
private:
A(A&); // declared, not defined
void operator= (A&); // declared, not defined
public:
A() { //do regular stuff }
}
However, if you are using C++11/C++14, you can use the delete keyword for more explicit case of this:
class A {
public:
A() { //do regular stuff }
A(A&) = delete;
void operator= (A&) = delete;
}
Since the move constructor and the move assignment operators will not be generated if you declare any of the destructor / copy constructor / assignment operator, you don't need to the same thing for them.
You can just = delete; the copy assignment operator:
class A {
// ...
void operator=(A) = delete;
};
Alternatively, if you don't use C++11 you can make the copy assignment private.
You can define the assignment operator as deleted. For example
class A{
public:
A(){/*need to initialize something here*/}
A & operator =( const A & ) = delete;
};
Or you can declare it private.
class A{
public:
A(){/*need to initialize something here*/}
private:
A & operator =( const A & );
};

avoiding duplication in the assignment operator of a derived class

Consider the assignment operators in classes Parent and Child, below.
#include <iostream>
class Parent
{
public:
Parent(){};
virtual ~Parent(){};
Parent& operator=(const Parent& other){mP = other.mP; return *this;};
void setP(double inP){mP = inP;};
double getP(){return mP;};
protected:
double mP;
};
class Child : public virtual Parent
{
public:
Child(){};
virtual ~Child(){};
Child& operator=(const Child& other)
{
mC = other.mC;
mP = other.mP;// this line
return *this;
};
void setC(double inC){mC = inC;};
double getC(){return mC;};
protected:
double mC;
};
Is here a way to avoid the duplicate line mP = other.mP;?
The reason I am asking is that as the number of bases get higher and the inheritance structure gets more complicated, it is easy to lose track of members.
EDIT
The reason I need to implement the operator= is that it needs to check some things before the assignments.
Just call the Parent operator:
Child& operator=(const Child& other)
{
mC = other.mC;
Parent::operator=(other);
return *this;
}
Or really, don't implement either operator since both are trivial!
The best way to avoid this issue is to remove both of your operator= functions.
The compiler-generated operator= applies operator= to each member variable and base class, which is just what you were trying to do anyway.
Re-implementing the wheel just makes your code harder to read and maintain -- and sometimes less efficient.
Child& operator=(const Child& other) {
mC = other.mC;
mP = other.mP;
}
you can invoke the assignment operator of the parent prior to the child specific assignment in this way:
Child& operator=(const Child& other)
{
Parent::operator=(other);
mC = other.mC;
return *this;
};

Public deleted or private default ctor/assignment/copy ctor?

If I want to forbid copy construction/assignment then is:
class foo
{
public:
foo(const foo&) = delete;
foo& operator = (const foo&) = delete;
};
The same as:
class foo
{
private:
foo(const foo&) = default;
foo& operator = (const foo&) = default;
};
Which is the right way and why?
The right way is the first solution : the copy constructor and assignment operators are not defined, so any attempt to use them will not compile.
class foo
{
public:
foo(const foo&) = delete;
foo& operator = (const foo&) = delete;
};
The second is declaring and defining the implicitly generated forms as private :
An object of type foo is allowed to copy itself.
Any friend class or method is also allowed to copy a foo
So copy construction/assignment is still possible.
You could also use boost::noncopyable as a base class, it does exactly that with c++11 (see the source code here)

warning assignment operator class reference

i have this code:
class ABC{
public:
ABC(std::ostream& os) : _os(os) {}
void operator() (const Stud* course) {
Stud->print(_os);
}
ABC& operator=(const ABC& other); //Declaration of operator=
private:
std::ostream& _os;
};
befor i define assignment operator i get warning "assignment operator could not be generated".
i want assignment between object this class do nothing, its just class print in for_each algorithm.
i try write :
ABC& operator=(const ABC& other){
return *this;
}
but still get warning the other not use.
how can i define assignment operator do nothing. (no Use the #pragma warning statement to suppress the warning).
thanks!
To get rid of the warning about an unused argument, just don't name it:
ABC& operator=(const ABC&){
return *this;
}
The reason that the compiler can't generate an assignment operator for your class is that it has a reference variable, and these can only be initialised, never re-assigned.
If you don't need an assignment operator, but only added one to make the compiler happy, you can declare it private and then not provide an implementation.
Few problems in your code...
class ABC
{
public:
ABC(std::ostream& os) : _os(os) {}
void operator() (const Stud* course)
{
//Stud->print(_os); // you can't use Stud here - this is wrong
course->print(_os);
}
ABC& operator=(const ABC& other); //Declaration of operator=
private:
std::ostream& _os;
};
Additionally, as operator() defines course as const Stud* the print method in Stud class should be defined as const as well.
other than that, the code compiles perfercly.

How to make a C++ class produce non cloneable objects

How can I make a Class non-cloneable like we can do in Java while creating singleton.
Is there any condition we can put on copy constructor so that an exception can be thrown if user tries to make a copy of an object?
I am a novice in C++ so kindly add any info to this or redirect if an answer is already available for the same.
Just declare copy constructor and copy assign operator private
in C++03
class NonCopyable
{
public:
NonCopyable() { }
private:
NonCopyable(const NonCopyable&);
NonCopyable& operator=(const NonCopyable&);
};
Also you can make a class derive from NonCopyable, AnotherType is un-copyable
class AnotherNonCopyable : private NonCopyable
{
public:
AnotherNonCopyable () {}
}
With C++11:
class NonCopyableType
{
public:
NonCopyableType(const NonCopyableType&) = delete;
NonCopyableType& operator=(const NonCopyableType&) = delete;
};
You can delete the copy constructor and assignment operator:
struct Foo
{
Foo(const& Foo) = delete;
Foo& operator=(const Foo&) = delete;
};
If you don't have C++11 support, make them private, and don't implement them:
struct Foo
{
private:
Foo(const& Foo);
Foo& operator=(const Foo&);
};
Note In C++, class and struct are essentially the same.
Declare the copy-semantics as delete:
//C++11 only
MyClass(MyClass const &) = delete;
MyClass& operator=(MyClass const &) = delete;
That makes the class non-copyable!
//pre-C++11 code
private:
MyClass(MyClass const &); //declare only, don't define it
MyClass& operator=(MyClass const &); //declare only, don't define it
This should also work!
Is there any condition we can put on copy constructor so that an
exception can be thrown if user tries to make a copy of an object.
if you make the copy constructor private, The code will not compile when the programmer tries to make another copy. This is probably better than detecting the error with an exception at runtime.
class foo {
private:
operator = ( const foo& f);
};