More Effective C ++ Terms 4

zhaozj2021-02-08  315

Terms 4: Avoid useless default constructor

Default constructor (referring to constructor without parameters) is a method that makes you have no midplane in the C language. The constructor can initialize the object, and the default constructor can be initialized without using any external data when establishing an object. Sometimes this method is good. For example, some behavior characteristics are also reasonable to initialize an empty value or an uncertain value, as well as a linked list, a hash table, a diagram, and the like can also be initialized to an empty container.

But not all objects belong to the above type. For many objects, it is unreasonable to adversely utilize external data. For example, there is no meaning of an address book object that does not enter a name. In some companies, all devices must be marked with a company ID number, so when the object is established to model a device, the object is not provided, and the object established is not meaningful.

In a perfect world, the class that can be established without any data can contain the default constructor, and the data that needs data to establish an object cannot contain the default constructor. Ugh! But our real world is not perfect, so we must consider more factors. Especially if a class does not have a default constructor, there will be some limitations.

Consider having such a class, it represents the company's equipment, this class contains a company's ID code, this ID code is forced to be parameters for constructor:

Class EquipmentPiece {

PUBLIC:

EquipmentPiece (int IDnumber);

...

}

Because the EquipmentPiece class does not have a default constructor, it will encounter problems in three cases. The first middle situation is to establish an array. In general, there is no way to deliver parameters to constructor when establishing an object array. So in general, it is impossible to establish an EquipmentPiece object array:

EquipmentPiece Bestpieces [10]; // Error! No correctly

// EquipmentPiece constructor

Equipmentpiece * bestpieces =

New equipmentpiece [10]; // Error! As with the above problem

However, there are still three ways to avoid this restriction. One solution to the use of non-Heap Arrays (ie, assigning memory in the stack. Translator Note) is the necessary parameters when the array is defined:

INT ID1, ID2, ID3, ..., ID10; // Storage device ID number

// variable

...

EquipmentPiece Bestpieces [] = {// correctly, provide construct

Parameters of equipmentpiece (id1), // function

EquipmentPiece (ID2),

EquipmentPiece (ID3),

...,

EquipmentPiece (ID10)

}

But unfortunately, this method cannot be used in a pile (HEAP)

arrays

Definition.

A more common solution is to use the pointer array instead of an object array:

Typedef equipmentpiece * pep; // PEP pointer points to

// An EquipmentPiece object

Pep Bestpieces [10]; // correct, no call constructor

PEP * bestpieces = new PEP [10]; // is also correct

Each pointer in the pointer array is reassigned to point to a different EquipmentPiece object: for (int i = 0; i <10; i)

Bestpieces [i] = new equipmentpiece (id number);

However, this method has two shortcomings, and the first you must delete the object points to each pointer in the array. If you forget, a memory leak will occur. The second increased memory distribution, because you need space to accommodate the EquipmentPiece object, you also need space to accommodate pointers.

If you assign RAW MEMORY for arrays, you can avoid waste of memory. Use the Placement New method (see Terms 8) to construct an EquipmentPiece object in memory:

/ / Assign enough memory for arrays of 10

// EquipmentPiece object; for details, see Terms 8

// Operator new [] function

void * rawMemory =

Operator new [] (10 * sizeof (equipmentpiece));

// Make Bestpieces Point To It So It Can Be Treated as an

// Equipment arch arr

Equipmentpiece * bestpieces =

Static_cast (rawmemory);

// Construct the equipmentpiece Objects in The Memory

// Use "Placement New" (see Terms 8)

For (int i = 0; i <10; i)

NEW (& Bestpieces [i]) Equipmentpiece (ID Number);

Note that you still have to provide constructor parameters for each EquipmentPieCe object. This technology (also known as array to pointers. Array-of-pointers) allows you to create an object array without default constructor. It does not bypass the need for constructor parameters, can't do it. If you can do it, you can't guarantee that the object is correctly initialized.

Disadvantages using Placement New In addition to Most programmers are unfamiliar with it (can be used to use it), it is necessary to manually call the destructor of array objects when you don't want it to continue to use. Operator delete [] to release RAW Memory (please refer to Terms 8):

// In contrast to construct the BestPIECES object

// Deconstruct it.

For (int i = 9; i> = 0; --I)

Bestpieces [i]. ~ Equipmentpiece ();

// deallocate the Raw Memory

Operator

Delete []

Rawmemory;

If you have forgotten this request or use this array to delete a method, then your program will run unpredictable. This is because directly deleting a memory pointer that is not assigned with a New operator, and the result is not defined.

DELETE [] Bestpieces; // Nothing! Bestpieces

/ / Is not allocated with a New operator.

For more information about New, Placement New and how they use the constructor, the destructor, please see Terms 8.

The second problem caused by the default constructor is not defined in the class is that they cannot be used in many template-based container classes. Because of the instantiation of a template, the type parameters of the template should provide a default constructor, which is a common requirement. This requirement always comes from the inside of the template and is established in the template parameter type array. For example, an array template class: Template

Class array {

PUBLIC:

Array (int size);

...

Private:

T * Data;

}

Template

Array :: Array (int size)

{

Data = new t [size]; / / for each array element

... // call T :: t () in turn

}

In most cases, the demand for default constructor can be eliminated by a carefully designed template. For example, the standard VECTOR template (generating a class similar to the scalable array) does not have the required default constructor without the type parameters of the scalable. Unfortunately, many template classes do not design carefully, so that there is no default constructor class that cannot be compatible with many templates. When C programmers understand the template design, such problems should not be prominent. How long is this, it is entirely in personal creation.

Finally, when designing the virtual foundation class is to provide a default constructor or no two difficulties in default constructor. It is difficult for the default constructor that is difficult to work. Because almost all derived classes must provide parameters for the virtual base class constructor in instantiation. This requires all derived classes (no matter how far) from the virtual basal class without the default constructor, must know and understand the parameters of the default base class constructor. The author of the derived class will not hope and like this.

Because these strongly added various limits on classes without default constructors, some people believe that all classes should have default constructor, even if the default constructor does not have enough data to initialize an object. For example, the advocator of this principle will modify the EquipmentPiece class:

Class EquipmentPiece {

PUBLIC:

Equipmentpiece (int IDnumber = unspecified);

...

Private:

Static const Int unspecified; // ID value is uncertain.

}

This allows this to establish an equipmentpiece object

Equipmentpiece e; // This legal

Such modifications make other member functions complicated because it is no longer able to ensure meaningful initialization of the EquipmentPieCe object. Suppose it creates an EquipmentPiece object that is not meaningless without ID, then most member functions must detect if the ID exists. If there is no ID, they will have to know how to make mistakes. However, this is often unclear, and many of the code is not available, just throwing an exception or calling a function termination program. When this situation occurs, it is difficult to say that the default constructor is provided to give up a guarantee mechanism whether this approach can improve the overall quality of the software.

转载请注明原文地址:https://www.9cbs.com/read-994.html

New Post(0)