C ++ should not use # define, but replace it with const, enum, and inline.

Source: Internet
Author: User

For example, the program file starts with the following # define statement.

Copy codeThe Code is as follows: # define N 10
# Define PI 3.14
# Deprecision MAX 10000
# Define Heigth 6.65
...
...

If the program runs an error here, and there is an error when we use these constants, the editor should throw an error message. If this information prompts 6.65, there is an error. OK. If you are lucky, you can remember or simply find what 6.65 means. If the program is very complicated, in addition, if 6.65 of the files are referenced, you will be confused about this? Maybe it will take a lot of time to track 6.65. What is it? Then locate the problem.
Why error 6.65? Instead of Heith? In the pre-compilation phase, 5.65 has been used to replace Heigth, and Height has not entered the system table. The solution is to replace the following statement:
Const double treeHeight = 5.68;
As a language constant, treeHeight is certainly known by the compiler and entered into the mark table. The error is not a number but a variable name, which helps to locate the problem.
Here are two special cases for constant replacement # define.
The first is to define a constant pointer. Here we need to define the pointer as a constant pointer, And the pointer also points to a constant, so it is in the following form:
Const char * const HZ = "Hang Zhou ";
In C ++, it is best to replace char * with a string object:
Const std: string HZ ("Hang Zhou ");
The second one is the exclusive class constant. First, it applies to the restriction class and must be declared as its member. Second, make sure that this constant has at most one entity and must be called a static member. For example:Copy codeThe Code is as follows: class People
{
Private:
Static const int Number = 10;
Int phoneNumbers [Number];
......
}

This shows declarative, not defined. Generally, C ++ requires you to define anything you use. You can also use enum to replace the macro of the formal function with inline or template. However, if it is a class-specific constant that is static and of the integer type (int, char, bool), special processing is required. As long as you do not marry them, you only need to declare them, instead of providing the definition form. However, if the class exclusive constant address is used, the compiler will provide the definition sub-statement even if the class exclusive constant address is not used.
Static const int People: Number
No initial value is defined here because the initial value has been obtained during the declaration.

You can use enum to complete similar functions.Copy codeThe Code is as follows: class People
{
Private:
Enum {Number = 10 };
Int phoneNumbers [Number];
....
}

Enum is like # define, not const. Because the const address is valid, it is not legal to take an enum address, and the # define address is usually invalid. Therefore, you can use enum to prevent others from getting the address of a constant.

Next we will introduce a written examination questionCopy codeThe Code is as follows: # define PRODUCT (a, B) a * B
....
Int a = 5, B = 3, c;
C = PRODUCT (a + 3, B + 4 );

So what is the value of c? C = 5 + 3*3 + 4 = 18 instead of the 56 expected by the programmer. To achieve the expected result, write

# Define PRODUCT (a, B) (a) * (B ))
Maybe you will insist on writing macro functions, because you want to write only one macro function to complete the product operations of int, flaot, and double types. Let's look at the example below.

# Define MAX (a, B) (a)> (B )? (A) (B ))

Int a = 5, B = 3

MAX (++ a, B); // a is added twice

MAX (++ a, B + 4); // a is added once
The result of adding a may not be expected. You can use the template inline function to achieve the expected macro effect, and the efficiency is similar to that of the macro.Copy codeThe Code is as follows: template <typename T>
Inline void Max (const T & a, const T & B)
{
F (a> B? A: B );
}

The inline function is a compilation mechanism that cannot be seen from the code, but the execution efficiency of the program is different, generally, the compiler processes function calls in a way similar to an interrupt. That is, when a function call statement is executed, all the information is stored in the register, after executing the code of the function, retrieve the register value, return to the starting state of the function call, and continue to execute the code. After declared as an inline function, the compiler does not compile the function into a call function, but instead copies the code to the called place. Therefore, the efficiency is higher than that of common functions, and the steps for storing registers and obtaining register information are less.
In addition, it is recommended that the inline function be written to the. h file or directly written to the class.
Const allows programmers to specify a semantic constraint that cannot be modified. The Compiler enforces this constraint. It indicates that the modified value remains unchanged. Const can modify constants in the global or namespace scope externally in classes, or modify files, functions, static objects, and pointers. In the const application, pay attention to the position where the keyword const appears in "*". If it is on the left, it indicates that the value to be pointed is a constant. If it is on the right, it indicates that the pointer itself is a constant. The union of the two functions is displayed. The following are some special points:
(1) cosnt in the iterator
Const std: vector <int >:: iterator iter = vec. begin (); // equivalent to iter cannot be changed

Std: vector <int >:: const_iterator citer = vec. begin (); // The content pointed to by iter cannot be changed.
(2) declaring the function return value as a constant not only reduces unexpected situations caused by programmer errors, but also eliminates the need to discard security and efficiency. For example:

Const operater * (const & lhs, const & rhs );
If (a * B = c); // the intention is that if (a * B = c) is written as this due to the careless programmer
If both a and B are built-in types, this code is unreasonable, but it may work if it is our custom type. If the declared return value is cosnt, this can be prevented.

(3) const member function, which is used to confirm that the member function can act on the const object. In addition, if the two member functions have different constants, they can be overloaded. The member function is followed by const, indicating that the function cannot change the member variables of the class (the following code is used for verification. If you try to assign values to the member, the compiler will report an error ). The principle is that the compiler considers it a read-only variable. In addition, most const objects are used for reference transfer or pointer transfer.Copy codeThe Code is as follows: # include <iostream>
# Include <string>

Class People
{
Public:
People (): m_sName (""), m_iAge (0 ){}
People (std: string name, int age): m_sName (name), m_iAge (age ){}
Void set (int age)
{
This-> m_iAge = age;
}

Void set2 (int age) const
{
This-> m_iAge = age;
}

Int get ()
{
Return this-> m_iAge;
}
Private:
Std: string m_sName;
Int m_iAge;
};

Int main (int argc, char ** argv)
{
People * p = new People ("sky", 8 );
P-> set (10 );
Std: cout <p-> get () <std: endl;
P-> set2 (12 );
Std: cout <p-> get () <std: endl;
Delete p;
Return 0;
}

Compile the file and report the following error message.
Const_test.cpp: In member function 'void People: set2 (int) const ':
Const_test.cpp: 16: error: assignment of data-member 'people: m_iAge 'in read-only structure
Const_test.cpp: 36: 2: warning: no newline at end of file
Cosnt overload (Note: only when the form parameter is a reference or pointer, whether the form parameter is const will affect ). We can try to remove the following code and pass in the const_int to call the void set (int age) function, which indicates that the const of the parameter does not work. Below is the verification codeCopy codeThe Code is as follows: # include <iostream>
# Include <string>
Class People
{
Public:
People (): m_sName (""), m_iAge (0 ){}
People (std: string name, int age): m_sName (name), m_iAge (age ){}
Void set (const int & age) const
{
Std: cout <"this is const" <std: endl;
}

Void test (int & age)
{
Std: cout <"this is non-const" <std: endl;
}

Void test (short age)
{
Std: cout <"this is non-const" <std: endl;
}

Int get ()
{
Return this-> m_iAge;
}
Private:
Std: string m_sName;
Int m_iAge;
};

Int main (int argc, char ** argv)
{
People * p = new People ("sky", 8 );
Const int const_int = 12;
P-> test (const_int );
Std: cout <p-> get () <std: endl;
Delete p;
}

(4) Repeat the code of the overload function. From experience, we can conclude that the functions that we reload through const often have a large amount of code that is repeated, or even the same. If most of the Code is repeated, we can write the code that is repeated into a function and call them separately. If the code is the same, we can call the const function in the non-const function to solve code duplication.Copy codeThe Code is as follows: class People
{
Public:
People (): m_sName (""), m_iAge (0 ){}
People (std: string name, int age): m_sName (name), m_iAge (age ){}
Void eat (const People & Person) const
{
Std: cout <"this person info is: {age =" <Person. m_iAge () <", name =" <Person. m_sName () <std: endl;
Std: cout <"eating" <std: endl;
Std: cout <"end" <std: endl;
}

Void eat (People & Person)
{
Std: cout <"this person info is: {age =" <Person. m_iAge () <", name =" <Person. m_sName () <std: endl;
Std: cout <"eating" <std: endl;
Std: cout <"end" <std: endl;
}
Private:
Std: string m_sName;
Int m_iAge;
};

Then, in the non-const eat function, convert * this type from People & to const People & to call the const function, that is, function overload.Copy codeThe Code is as follows: # include <iostream>
# Include <string>
Class People
{
Public:
People (): m_sName (""), m_iAge (0 ){}
People (std: string name, int age): m_sName (name), m_iAge (age ){}
Void eat (const People & Person) const
{
Std: cout <"this person info is: {age =" <Person. m_iAge <", name =" <Person. m_sName <"}" <std: endl;
Std: cout <"eating" <std: endl;
Std: cout <"end" <std: endl;
}

Void eat (People & Person)
{
Static_cast <const People &> (* this). eat (Person );
}
Private:
Std: string m_sName;
Int m_iAge;
};

Int main (int argc, char ** argv)
{
People Person ("sky", 8 );
Person. eat (Person );
}

The running result is

This person info is: {age = 8, name = sky
Eating
End

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.