More Effective C ++ Terms 7

zhaozj2021-02-08  237

Terms 7: Don't overload OverLoad &&, ||, or,.

Like C, C uses Boolean Expression to simplify the surchanting method (SHORT-CIRCUIT Evaluation). This means that once the true and false value of the Boolean expression is determined, even if some expressions are not tested, the Boolean expression also stops operations. E.g:

Char * p;

...

IF ((p! = 0) && (Strlen (P)> 10)) ...

You don't have to worry about being an empty time Strlen cannot operate correctly because if P does not equal 0 tests fail, Strlen will not be called. same:

INT Rangecheck (int index)

{

IF ((INDEX UpperBound) ...

...

}

If Index is less than LowerBound, it will not compare with UpperBound.

Previously, the above behavior characteristics were repeatedly infused to C and C programmers, so they all know this feature. And they also rely on short quotation methods to write programs. For example, in the first code described above, it is important to ensure that Strlen does not call when P is an empty pointer, because the C standard says (as the C standard says) uses an empty pointer to call Strlen, and the result is uncertain.

C allows custom && and || operators based on user-defined types. The method is to overload functions Operator && and Operator || You can overload or overload in each class. However, if you want to use this method, you must know that you are changing the rules of the game. Because you replace brief calculation by function calling. That is to say, if you overload the operator &&, the code is like this:

IF (Expression1 && Expression2) ...

For the compiler, it is equivalent to one of the following code:

IF (Expression1.operator && (Expression2)) ...

// when Operator && is A

// Member Function

IF (Operator && (Expression1, Expression2) ...

// when Operator && is A

// Global Function

This seems to be different, but the function call method is absolutely different from the short quotient method. First, when the function is called, it is necessary to calculate all of its parameters, so when the function functions operator & operator || requires calculations, in other words, there is no short calculation method. The second is that the C language specification does not define the calculation order of the function parameter, so there is no way to know which one of the expression 1 and the expression 2 is calculated. Completely computing with a short calculation method with the order from left parameters to right parameters.

So if you overload && or ||, there is no way to provide the behavior characteristics they expect and use, so don't overload && and ||.

The same reason is also suitable for parentheses operators, but before we study it, I still stop, let you be too surprised, "comma operator? Which comma operator?" Did exist.

Commergees operators are used to form an expression, you often meet it in the UPDATE PART. For example, the function of the second edition (Prentice-Hall, 1988), which is derived from the Kernighan's and Ritchie's Classic Books.

Void Reverse (Char S [])

{

For (int i = 0, j = strlen (s) -1;

i

i, --j) // Ah! Command operator!

{

INT C = S [I];

S [i] = s [j];

S [J] = C;

}

}

In the last part of the FOR cycle, I is incremented by simultaneous J is reduced. It is convenient to use a comma here because only one expression can be used in the last portion, and the value of the expression to change the I and J is illegal.

For built-in type & ||, C has some rules to define how they operate. Similarly, there is also a rule to define a computational method of a comma operator. A comma-containing expression first calculates the expression on the left side of the comma, then calculates the expression on the right side of the comma; the result of the entire expression is the value of the comma. Therefore, in the last part of the above cycle, the compiler first calculates i, then the result of the -j, comma expression is --j.

Maybe you want to know what you need to know? Because you need to imitate this behavior, if you want to boldly write your own comma operator function. Unfortunately, you can't imitate.

If you write a non-member function Operator, you cannot guarantee the expression of the expression on the left to calculate the on the right, because the two expressions are passed as a parameter when the function is called. But you can't control the calculation order of the function parameters. Therefore, the method of non-member functions is absolutely no.

The remaining only the possibility of writing member functions Operator. Even here you can't rely on the behavior characteristics of the expression of the expression of the comma first, because the compiler does not necessarily have to calculate this method. So you can't overload the comma operator to ensure that its behavioral characteristics are the same as they are expected. Overloading it is a completely rash behavior.

You may be thinking about whether this heavy dreamed is endless. After all, if you can override a comma operator, what else can't be overloaded? As shown, there are some restrictions, you can't overload the following operators:

* ::?:

New delete Sizeof TypeID

Static_cast Dynamic_cast const_cast reinterpret_cast

You can overload:

Operator New Operator Delete

Operator new [] operator delete []

- * /% ^ & | ~

! = <> = - = * = / =% =

^ = & = | = << >> >> = << = ==! =

<=> = && || -, -> * ->

() []

(About New and Delete also have Operator New, Operator Delete, Operator New [], and and operator delete [] information see clauses 8) Of course, it is not necessary to overload these operators. The purpose of operator overload is to make the program easier to read, write and understand, not to confuse others with your knowledge. If you don't have a good reason to overload the operator, don't be overloaded. It is difficult to find a good reason because of the good reason, because anything you work, you can't let their behavior characteristics are the same as what you expect.

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

New Post(0)