C ++ Study Notes (5) Miscellaneous

Source: Internet
Author: User

Const member functions
The main value of a const member function lies in the const object. We know that the const object cannot be modified. To ensure that the const object cannot be modified, the compiler stipulates that the const object can only call the const modified member function, it checks the member functions of this class to ensure that the object state is not modified when this function is called.
The Const object can only call the const member function, but not the const object can be called by all member functions. However, sometimes we also want the const object to have a non-const version. For example, define an acceptor class Accu:
[Cpp]
Class Accu {
Public:
Accu (): data (0 ){}
Accu & add (int d) {data + = d; return * this ;}
Const Accu & show () const {cout <data; return * this ;};
Private:
Int data;
}

It can be seen that the show function only shows the result, so it is a const member function. Now there is a programming style called chained programming style. To use the above class, we can write the following code:
[Cpp]
Accu ac;
Ac. add (1). add (30). show ();

Since each function returns a reference to the object itself, we can call the program in a chained style. I will not talk about the advantages of this style. Now I will mainly explain its problems. Careful kids shoes may find that the show function can only be called at the end, because it is a const member function, it returns a const reference to the object, that is, the following code will generate a compilation error:
[Cpp]
Ac. add (1). add (30). show (). add (6 );

You cannot call non-const member functions on a const object.

To solve this problem, we need to reload the show function and add a non-const version.
[Cpp]
Accu & show () {cout <data; return * this ;};

In this way, the problem is solved. In fact, there is such a function matching priority, that is, the non-const member function has a higher priority than the const member function. Therefore, after the overload, the non-const object must call the show function of the const version. Only the const object can call the show function of the const version.

Mutable data member
In reality, there may be such a requirement that the member variable can be modified even in the const object. In this case, the member can be modified with the mutable keyword, in this way, you can modify the value of this Member even in the const member function.

Class scope
We know that the member variables or types defined in the class can be directly referenced in the member functions of the class. Even if the member functions are defined outside the class, in fact, it can also be referenced directly in the parameter list, except for the return value type. The reason is that the function scope is determined only when the function name is met during compilation. That is to say, any member defined after the function name can directly reference the class, the returned values defined before it are naturally excluded. See the following example:
[Cpp]
Class {
Public:
Typedef int byte32;
Byte32 test (byte32 );
};
A: byte32 A: test (byte32 ){
// Some code
}

Byte32 is the type defined in class A. Because the returned value is out of the class scope, A: is required, but the parameter list is defined after the function name, so it is within the scope of the class, so A: modifier is not required.

Here, let's take a look at the name search mechanism of C ++ and consider the following definition:
[Cpp]
Typedef string Type;
Type initVal ();
Class Exercise {
Public:
//...
Type test ();
Typedef double Type;
Type setVal (Type );
Type initVal ();
Private:
Int val;
};
Type Exercise: setVal (Type parm ){
Val = parm + initVal ();
}

Can you clearly tell where the types are defined here?

The name search mechanism of C ++ is like this. If you are looking for a type name, you should first find it in the function (or block) used for this type. If you cannot find it, find the part before the function definition in the class where it is located. If it still cannot be found, search before the definition of the class (if the member function is defined outside the class, it is found before the definition of the member function); if it is a variable name or function name, the difference is that, when we look for the class scope, we search for the entire class, not just the previous part of the variable.

So let's look back at the code. The Type initVal () returned Type in the class is actually the global Type, and what Type is in the Type initVal () in the class. Because this Type is not used inside the function, it eliminates the need to look for the function scope. It directly finds the class scope, so that the Type defined in the class is found. The Declaration of the setVal function is the same as that of the class. The key is its definition. As we mentioned earlier, the parameter list of the member function is in the class scope, so the Type in the parameter list is the Type defined in the class, but the return value is different. It is the global Type. Now let's look at the internal function. For the variable parm, the compiler first searches for the internal function and finds the parma in the parameter list. However, val and initVal are declared inside the function. Therefore, the next step is to search for the entire class scope and find their declared positions. There is also a function declaration Type test () in the class; since its declaration is placed before the Type definition in the class, we have said before, during compilation, only the part before the Type name is found in the class scope, so the definition of Type cannot be found here, then, the compiler searches the environment outside the class definition to find the global Type definition.

Well, it seems a bit messy here. I didn't want to write this part, because in actual development, naming repetition should be avoided as much as possible, so this part is actually more theoretical than practical significance, in order to improve the notes, I wrote it down. Skip it if you do not understand it.
Initialization list
In the class constructor, C ++ provides a mechanism for us to initialize class members. This is the initialization list. Consider the following two methods to define the constructor:
[Cpp]
A (B & pb ){
<Span style = "white-space: pre"> </span> B = pb;
}
 
A (B & pb): B (pb ){
}

In the second method, the initialization list is followed by the colon. When this part is omitted, the compiler will use the default constructor to generate an initialization statement for each class member, so the first method is equivalent:
[Cpp]
A (B & pb): B (){
<Span style = "white-space: pre"> </span> B = pb;
}

Consider the two methods. If type B is a native data type, there is actually no difference between the two, but if it is a class type, you have to consider the performance overhead between the two, the first method is to call the default constructor first, and then assign values. The second method is to directly call the copy constructor. Assume that the two constructor functions are defined as follows:
[Cpp]
B (): C (0 ){
}
 
B (B & B): C (B. c ){
}

In this case, the performance of the default constructor and the copy constructor is the same, but the first method has the overhead of assigning values. If this method is used, if their performance and overhead differences are not explicit enough, consider the following situations:
[Cpp]
A (C & c): B (){
<Span style = "white-space: pre"> </span> B = B (c );
}
 
A (C & c): B (c ){
}

This time, the bottom one is to call the default constructor first, then call a non-default constructor, and then call a = operation (here we can reload it ), in the second method, you only need to call a non-default constructor once.
Therefore, in some cases, the performance of the initialization list and the initialization in the constructor body is not significantly different, but in other cases, using the initialization list will be more efficient. This is efficiency. In fact, in some cases, if the member variable does not provide the default constructor, we must use the initialization list. Therefore, when both are in the alternative, the initialization list is often our better choice, but this is just a suggestion, not a mandatory requirement. The specific situation depends on our business logic.


Author: justaipanda

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.