See title.
I have:
class Foo {
private:
Foo();
public:
static Foo* create();
}
What need I do from here to make Foo un-copyable?
See title.
I have:
class Foo {
private:
Foo();
public:
static Foo* create();
}
What need I do from here to make Foo un-copyable?
class Foo {
private:
Foo();
Foo( const Foo& ); // non construction-copyable
Foo& operator=( const Foo& ); // non copyable
public:
static Foo* create();
}
If you're using boost, you can also inherit from noncopyable : http://www.boost.org/doc/libs/1_41_0/boost/noncopyable.hpp
EDIT: C++11 version if you have a compiler supporting this feature:
class Foo {
private:
Foo();
public:
Foo( const Foo& ) = delete; // non construction-copyable
Foo& operator=( const Foo& ) = delete; // non copyable
static Foo* create();
}
Note that deleted methods should be public: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-delete
Make the copy constructor and the assignment operator private as well. Just the declaration is enough, you don't have to provide an implementation.
In C++11, you can explicitly disable the creation of default copy and assignment constructor by placing = delete
after the declaration.
From Wikipedia:
struct NonCopyable {
NonCopyable() = default;
NonCopyable(const NonCopyable&) = delete;
NonCopyable & operator=(const NonCopyable&) = delete;
};
The same goes for classes of course.
Just another way to disallow copy constructor,For convenience, a DISALLOW_COPY_AND_ASSIGN macro can be used:
// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for a class
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&) = delete; \
void operator=(const TypeName&) = delete
Then, in class Foo:
class Foo {
public:
Foo(int f);
~Foo();
private:
DISALLOW_COPY_AND_ASSIGN(Foo);
};
#include <boost/utility.hpp>
class Foo : boost::noncopyable {...
But as Scott Meyers once said..."It's a fine class, it's just that I find the name a bit un, err non natural", or something like that.
To add a bit there.
The traditional solution is, as has been said, to declare both Copy Constructor
and Assignment Operator
as private
, and not to define them.
private
, this will lead to a compile-time error from anyone trying to use them that has not access to the private parts of the class...undefined symbol
, either at link-time (if you check for those there) or most probably at run-time (when trying to load the library).Of course, it is quite a bother in the second case because you then have to check your code by yourself since you do not have the indication of the file and line at which the error occurs. Fortunately it's limited to your class methods and friends.
Also, it is worth noting that these properties are transitive down the inheritance and composition road: the compiler will only generate default versions of the Default Constructor
, the Copy Constructor
, the Assignment Operator
and the Destructor
if it may.
This means that for any of those four, they are automatically generated only if they are accessible for all the bases and attributes of the class.
// What does boost::noncopyable looks like >
class Uncopyable {
public:
Uncopyable() {}
private:
Uncopyable(const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
};
This is why inheriting from this class (or using it as an attribute) will effectively prevents your own class to be copyable or assignable unless you define those operators yourself.
Generally inheritance is chosen over composition there for 2 reasons:
Uncopyable
, even if polymorphism may not be that usefulEBO
or Empty Base Optimization
, while an attribute will be addressable and thus will occupy memory (in each instance of the class) even if it does not actually need it, the compiler has the possibility not to add this overhead for a base class.You could, alternatively, declare the operators private and not define them in your own class, but the code would be less self-documenting, and you would not be able to automatically search for those class that have this property then (unless you have a full-blown parser).
Hope this shed some light on the mechanism.
Uncopyable
incomplete without explicitly defining the constructor since it won't be automatically generated on account of the presence of the other constructors? For example, you get "no appropriate default constructor available" with this: rextester.com/SFWR22041 Thanks for your helpful answer! I especially appreciate the motivation you've given for using inheritance. –
Mcclees The typical way to make a C++ object non-copyable is to explicitly declare a copy constructor and copy-assignment operator but not implement them. This will prevent the compiler from generating its own. (Typically this is done in conjunction with declaring them private
so that it generates a compilation error instead of a linker error.)
There also is the boost::noncopyable
class that you can inherit from, which does what I described above.
The good practice in C++11 is to declare the copy constructor and assignment as publicly deleted. Not privately deleted, publicly deleted: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-delete
Make the copy constructor private.
Foo(const Foo& src);
You don't need to implement it, just declare it in the header file.
This is what I use:
/* Utility classes */
struct NoCopy
{
public:
NoCopy() {}
private:
NoCopy(const NoCopy &);
};
struct NoAssign
{
private:
NoAssign &operator=(const NoAssign &);
};
struct NonInstantiable
{
private:
NonInstantiable();
};
struct NoCopyAssign : NoCopy, NoAssign
{
};
typedef NoCopyAssign NoAssignCopy;
In your case:
struct Example : NoCopy
{
};
© 2022 - 2024 — McMap. All rights reserved.