More Effective C ++ Terms 3

zhaozj2021-02-08  400

Terms 3: Do not use polymorphisms

The most important feature of the inheritance is that you can operate with the base class pointer or reference. Such pointers or references have behavioral polymorphisms, as if they have multiple forms. C allows you to operate the derived class in the base class pointer and reference. However, this is not a feature, because such code is not allowed to run as you wish.

Suppose you have a class BST (such as search tree object) and inheriting the derived class BALANCEDBST from the BST class:

Class BST {...};

Class BalancedBST: Public BST {...};

In a real program, such a class should be a template class, but in this example is not important, plus the template will only make the code more difficult to read. To facilitate discussion, we assume that BST and BalanceDBST contain only int type data.

There is such a function that prints the contents of each BST object in the BST type array:

Void PrintBSTARRAY (Ostream & S,

Const bst array [],

INT Numelements

{

For (int I = 0; i

s << array [i]; // assumes the BST class

} // Operate the operator <<

}

When you pass to the function a group variable containing the BST object, it can run normal:

Bst Bstarray [10];

...

PrintBSTARRAY (COUT, BSTARRAY, 10); // Operation is normal

However, consider what consequences when you pass the array variables containing the BalanceBST object to the PrintBSTARRAY function:

Balancedbst bbstarray [10];

...

PrintBSTARRAY (COUT, BBSTARRAY, 10); // will also run normal?

Your compiler will compile this function without warning, but then take a look at the loop code of this function: for (int i = 0; i

S << array [i];

}

The Array [i] here is just a necklace of a pointer algorithm: what it represents * (array). We know that Array is a pointer to array start addresses, but how big is the interval of each element memory address and an array of array? Their interval is i * sizeof (an object in an array) because there is an object between Array arrays [0] to [i]. In order to establish an execution code that correctly traverses an array, it must be able to determine the size of the object in the array, which is easy to do for the compiler. The parameter Array is declared as a BST type, so each element in the Array array is the BST type, so the interval of each element and the array start address is Be i * sizeof (BST).

At least your compiler is thinking. But if you pass an array variable containing the BalanceBST object to the PrintBSTARRAY function, your compiler will make mistakes. In this case, the compiler has just assume that the elements in the array are consistent with the size of the BST object, but each object size in the array is now consistent with BalanceBST. The length of the derived class is usually longer than the base class. We despise the length of the BalanceBST object ratio BST long. If so, the PRINTBSTARRAY function generated pointer algorithm will be wrong, and no one knows what kind of consequences if the PrintBSTARRAY function will happen if the BalanceBST array will use. No matter what the consequences are unpleasant.

If you try to delete an array containing derived class objects, a variety of issues will occur. The following is a possible incorrect approach. / / Delete an array, but first log out a delete information

Void DeleteArray (Ostream & logstream, Bst Array [])

{

Logstream << "Deleting Array At Address"

<< static_cast (array) << '/ n';

delete [] array;

}

BalancedBst * BaltreeArray = // Create an array of BalanceBST objects

New balancedbst [50];

...

DeleteArray (Cout, BaltreeArray); // Record this delete operation

This also hides the pointer algorithm you can't see. When a array is deleted, the destructor of each array element will also be called. When the compiler encounters this code:

delete [] array;

It is certainly like this to generate code:

// is in the order in contrast to the construction order

// Deconstruct objects in array arrays

For (INT i = number 1; i> = 0; - i)

{

Array [i] .bst :: ~ bst (); // Call Array [i]

} // Destructor

Because the loop statement you have written is not running at all, it is not possible to run normally when compiled into an executable code. The language specification says that an array containing the derived class object is removed by a base class pointer, and the result will be uncertain. This actually means that there is no better result of performing such code. The polymorphism and pointer algorithm cannot be mixed together, so the array and polymorphism cannot be used together.

It is worth noting that if you don't derive another specific class (such as BST), you are unlikely to make this error in this use polymorphic array. As explained in Terms 33, there is a lot of benefits from specific classes. I hope you read the contents of the Terms 33.

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

New Post(0)