Item 6: if you do not want to use compiler-generated functions (the compiler generates a function), explicitly reject
By Scott Meyers
Translator: fatalerror99 (itepub's nirvana)
Release: http://blog.csdn.net/fatalerror99/
A real estate agent sells a house. A software system that serves such an agent naturally requires a class to indicate the house to be sold:
Class homeforsale {...};
Every real estate agent will soon point out that each property is unique-no two are identical. In this case, createCopyThe idea of copying is confusing. How can you copy a unique object? Therefore, it is best to prevent such attempts to copy homeforsale object (object) from being compiled:
Homeforsale H1;
Homeforsale H2;
Homeforsale H3 (H1 );// Attempt to copy H1-shocould
// Not compile!
H1 = h2;// Attempt to copy H2-shocould
// Not compile!
Alas, this compilation method is not so easy to understand. Generally, if you do not want a class to support a function, you can simply not declare the function that gives it such a function. This policy does not work for copy constructor and copy assignment operator because, as shown in item 5, if you do not declare them, when someone wants to call them, the compiler will declare them for you.
This limits you. If you do not declare copy constructor (copy constructor) or copy assignment operator (copy assignment operator), the compiler can also generate them for you. Your class will still support copying ). On the other hand, if you declare these functions, your class will still support copying ). However, our goal at this time isPreventCopying (prevents copying )!
The key to solving this problem is that all the functions generated by the compiler are public. To avoid generating these functions, you must declare them yourself, but you have no reason to declare them as public. Instead, you should declare copy constructor and copy assignment operatorPrivate(Private. By explicitly declaring a member function (member function), you can prevent the compiler from generating its own version, and declare this function as private to prevent others from calling it.
Generally, this scheme is not very safe, because Member and friend functions can still call your private function. In other words, unless you are very smartDefineDefine them. Then, when someone accidentally calls them, there will be an error in link-time. This tip-declare that member functions (member function) is private but deliberately does not implement it-it is really good, in the iostreams library of C ++, there are several classes that use this method prevent copying (to prevent copying ). For example, take a look at the definition of ios_base, basic_ios, and sentry in the implementation of the standard library, and you will see copy constructor (copy constructor) and copy assignment operator (copy assignment operator) are declared as private and not defined.
Using homeforsale is simple:
Class homeforsale {
Public:
...
PRIVATE:
...
Homeforsale (const homeforsale &); // Declarations only
Homeforsale & operator = (const homeforsale &);
};
You will notice that I have omitted the functions 'parameters (function parameter) Name. This is not necessary, but a common practice. After all, functions will not be implemented and will be used less. What is the need to specify the parameter name?
For the above class definition (class definition), the compiler will prevent customers from attempting to copy homeforsale objects (object). If you are not careful in member (member) or friend function (friend function) in this case, the Connection Program will protest.
It is also feasible to advance the link-time error (connection-time error) to the Compilation Time (early error detection is better than late error detection after all ), by not declaring copy constructor (copy conuctor) and copy assignment operator (copy assignment operator) in homeforsale itself as private, but in a prevent copying (prevent copying) the base class (base class) is specially designed. The base class itself is very simple:
Class uncopyable {
Protected: // allow construction
Uncopyable () {}// and destruction
~ Uncopyable () {}// derived objects...
PRIVATE:
Uncopyable (const uncopyable &); //... but prevent copying
Uncopyable & operator = (const uncopyable &);
};
To prevent copying homeforsale objects (object), we must now make it inherit from uncopyable:
Class homeforsale:Private uncopyable{// Class no longer
... // Declares copy ctor or
}; // Copy assign. Operator
This is because if someone -- or even Member (member) or friend function (friend function) -- tries to copy a homeforsale objects (object ), the compiler will try to generate a copy constructor (copy constructor) and a copy assignment operator (copy assignment operator ). As explained in item 12, the compiler-generated versions (compiler-generated version) of these functions will attempt to call the corresponding functions of the base class, and these calls will be rejected, because in base class (base class), the copy operation is private.
The implementation and use of uncopyable includes some nuances. For example, the uncopyable inheritance does not have to be public (public) (see item 32 and 39), and The uncopyable destructor (destructor) it does not need to be virtual (virtual) (see item 7 ). Uncopyable does not contain data, so it meets the empty base class optimization (empty Base Class Optimization) condition described in item 39, but because it is a base class (base class ), the application of this technology cannot introduce multiple inheritance (Multi-inheritance) (see item 40 ). Conversely, multiple inheritance (Multi-inheritance) Sometimes invalidates empty base class optimization (empty Base Class Optimization) (see item 39 ). Generally, you can ignore these nuances and use uncopyable only as demonstrated here, because it works like advertising. You can also use an available version in boost (see item 55. The class name is noncopyable. That is a good thing. I just found that name is a bit un-(no ......) Hmm ......NonNatural (unnatural ).
Things to remember
- To reject the functions automatically provided by the compiler, declare the corresponding member functions (member function) as private and do not provide implementations (implementation ). Using a base class (base class) similar to uncopyable is one of the methods.