Objective C ++ Reading Notes (4)

Source: Internet
Author: User

Article 05: understand which functions are compiled and called in C ++

Knowing what functions C ++ silentlywrites and CILS

When will an emptyclass no longer be an empty class )?

The answer is after C ++ processes it. If you do not declare a copy constructor, A copyassignment operator, and a destructor, the compiler will declare a version of the constructor. In addition, if you do not have a constructor, the compiler will declare a default constructor for you. All these functions are declared as public and inline. Therefore:

Class Empty {};

In essence, it is the same as writing it like this:

Class Empty {

Public:

Empty () {...} // default constructor

Empty (const Empty & rhs) {...} // copy constructor

~ Empty () {...} // destructor

Empty & operator = (const Empty & rhs) {...} // copy assignmentoperator

};

These functions are created by the compiler only when they are called. The following code will prompt every function generation:

Empty e1; // default constructor & destructor

Empty e2 (e1); // copy constructor

E2 = e1; // copy assignment operator

Default constructor and destructor are mainly used to place "behind-the-scenes code" for the compiler, such as calling constructors and destructor of base and non-static data members. Note that the generated destructor is non-virtual, unless its class is inherited from a base class, the base class declares a virtual destructor (in this case, the virtualness of the function (virtual) comes from the base class ). For the copy constructor and copy assignment operators, the compiler generates a version that simply copies each non-static member object of the source object to the target object.

Template <typename T>
Public:
NamedObject (const char * name, const T & value );
NamedObject (const std: string & name, const T & value );

...

Private:
Std: string nameValue;
T objectValue;
};

If you have already designed constructor for a class that requires real parameters, you don't have to worry that the compiler will add another default constructor to block your version. NamedObject neither declares the copy constructor nor the copy assignment operator, so the compiler will generate these functions (if they are called ):

NamedObject <int> no1 ("SmallestPrime Number", 2 );

NamedObject <int> no2 (no1); // callcopy constructor

The copy constructor generated by the compiler uses no1.nameValue and no1.objectValue to initialize no2.nameValue and no2.objectValue respectively. The nameValue type is string, and the standard string type has a copy constructor. Therefore, the no1.nameValue parameter is used to call the copy constructor of string to initialize no2.nameValue. On the other hand, NamedObject <int>: The objectValue type is int (in this template instantiation, T is int), and int Is the built-in type, therefore, no2.objectValue will be initialized by copying every bits of no1.objectValue. The copy assignment operator generated by the compiler for NamedObject <int> essentially performs the same behavior as the copy constructor.

For example, if NamedObject is defined as follows, nameValue is a reference to string, and objectValue is a const T:

Template <class T>
Class NamedObject {
Public:
// The following const name is no longer accepted by the const function, because nameValue is now a // reference-to-non-const string
NamedObject (std: string & name, const T & value );

... // As before, assume operator = is not declared

Private:
Std: string & nameValue; // here is reference
Const T objectValue; // here is const
};

Now, consider what will happen below:

Std: string newDog ("Persephone ");

Std: string oldDog ("Satch ");

NamedObject <int> p (newDog, 2 );

NamedObject <int> s (oldDog, 36 );

P = s; // What happens to the member variable of p now?

Note that nameValue and C ++ do not provide a method to point a reference to another object. In this case, C ++ refuses to compile the value assignment code. If you want a class containing referenced members to support Value assignment, you must define the copy assignment operator. For classes that contain const members, the compiler has similar behavior (like the objectValue in this example ). Changing a const member is illegal, so the value assignment function generated by the compiler implicitly cannot determine how to handle it.

Finally, if the copy assignment operator of the base class is declared as private, the compiler rejects generating an implicit copy assignment operator for the derived class it inherits. After all, the compiler can process the baseclass component of the copy assignment operator generated by the derived class, but they certainly cannot call member functions that the derived class has no permission to call.

· The compiler can implicitly generate a class default constructor (default constructor), copy constructor (copy constructor), and copy assignmentoperator (copy assignment operator) and destructor (destructor ).

 

Clause 06: if you do not want to use a function automatically generated by the compiler, explicitly reject it.

Explicitly disallow the use ofcompiler-generated functions you do not want

A real estate agent sells a house. A software system serving such an agent naturally has a category to indicate the house to be sold. each property is unique, so it is best to make behavior similar to this attempt to copy a HomeForSale object not through compilation:

Class HomeForSale {...};

HomeForSale h1;

HomeForSale h2;

HomeForSale h3 (h1); // an attempt to copy h1 should not be compiled

H1 = h2; // an attempt to copy h2 should not be compiled

Blocking compilation of this type of code is not that simple. If you do not declare the copy constructor and the copy assignment operator, and someone wants to call them, the compiler will declare them for you. On the other hand, if you declare these functions, your class will still support copying, and our purpose at this time is to prevent 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 there is no reason to declare them as public. On the contrary, the copy constructor and the copy assignment operator should be declared as private. By explicitly declaring a member function, you can prevent the compiler from generating its own version, and declare this function as private. This can prevent others from calling it.

It is really good to declare a member function as private but deliberately not implement it. In the iostreams library of C ++, several classes use this method to prevent copying. For example, in the implementation of the standard library, ios_base, basic_ios, and sentry, the copy constructor and the copy assignment operator are declared as private and not defined.

Using HomeForSale is simple:

Class HomeForSale {
Public:
...

Private:
...
HomeForSale (const HomeForSale &); // only declares
HomeForSale & operator = (constHomeForSale &);
};

You will notice that I have omitted the name of the function parameter. Parameter names are not necessary, but they are always used to writing. After all, functions will not be implemented and will be used less. What is the need to specify a parameter name? With the above class definition, the compiler will block the customer's attempt to copy the HomeForSale objects object. If you accidentally do this in a member function or a friend function, the connector will protest.

It is also feasible to advance the connection error to the compilation time (it is better to discover the error earlier than it is later ). In a base class specially designed for prevent to prevent copying, you can declare the copy constructor and the copy assignment operator as private. This base class is very simple:

Class Uncopyable {
Protected:

Uncopyable () {}// allow derived Object Construction and Structure
~ Uncopyable (){}

Private:
Uncopyable (const Uncopyable &); // But copying is blocked
Uncopyable & operator = (const Uncopyable &);
};

To prevent the HomeForSale object from being copied, the only thing we need to do is inherit Uncopyable:

Class HomeForSale: private Uncopyable {
... // Class no longer declares the copy constructor or the copy assignment operator

};

The implementation and use of Uncopyable includes some nuances. For example, the Uncopyable inheritance does not have to be public, and the Uncopyable destructor does not have to be virtual. Because Uncopyable does not contain data, it meets the condition of emptybase class optimization, but because it always plays a base class, using this technology may lead to multiple inheritance. Generally, you can ignore these nuances and use Uncopyable only as demonstrated here. You can also use the noncopyable class in Boost.

· To reject the functions automatically provided by the compiler, declare the corresponding member functions (member functions) as private and do not provide implementations (implementations ). Using a base class (base class) similar to Uncopyable is one of the methods.

 

From pandawuwyj's column

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.