Typename and typedef keywords, difference

Source: Internet
Author: User

The explicit keyword in C ++ is used to modify the class constructor, indicating that the constructor is explicit. Since there is an "Explicit", there must be "implicit ", so what is explicit and what is implicit?

If the constructor of the C ++ class has a parameter, a default conversion operation will be performed during compilation: Convert the data of the corresponding data type of the constructor to this type of object, as shown below:
Class myclass
{
Public:
Myclass (INT num );
}
....
Myclass OBJ = 10; // OK, convert int to myclass
In the code above, the compiler automatically converts an integer to a myclass object, which is actually equivalent to the following operation:
Myclass temp (10 );
Myclass OBJ = temp;
All the operations above are called "implicit conversions ".

What should we do if we want to avoid this automatic conversion function? Hey, this is the role of the keyword explicit. Declare the class constructor as "display", that is, add the explicit it before declaring the constructor, this will prevent this automatic conversion operation. If we modify the above myclass constructor to display, the following code cannot be compiled, as shown below:
Class myclass
{
Public:
Explicit myclass (INT num );
}
....
Myclass OBJ = 10; // err, can't non-explict convert

Class isbn_mismatch: public STD: logic_error {
Public:
Explicit isbn_missmatch (const STD: string & S): STD: logic_error (s ){}
Isbn_mismatch (const STD: string & S, const STD: string & LHS, const STD: string & RHs ):
STD: logic_error (s), left (LHS), right (RHs ){}
Const STD: String left, right;
Virtual ~ Isbn_mismatch () Throw (){}
};

Sales_item & operator + (const sales_item & LHS, const sales_item RHs)
{
If (! LHS. same_isbn (RHs ))
Throw isbn_mismatch ("ISBN missmatch", LHS. Book (), RHS. Book ());
Sales_item RET (LHS );
RET + RHS;
Return ret;
}

Sales_item Item1, item2, sum;
While (CIN> Item1> item2)
{
Try {
Sun = Item1 + item2;
} Catch (const isbn_mismatch & E)
{
Cerr <E. What () <"Left ISBN is:" <E. Left <"right ISBN is:" <E. Right <Endl;
}
}

It is used for user-defined constructor. It specifies that it is the default constructor and cannot be used to convert constructor. there are three constructor types: 1 copy constructor 2 convert constructor 3 General constructor (my own terminology ^_^)
In addition, if a class or structure has multiple constructors, the constructor modified by explicit is the default one.

Class isbn_mismatch: public STD: logic_error {
Public:
Explicit isbn_missmatch (const STD: string & S): STD: logic_error (s ){}
Isbn_mismatch (const STD: string & S, const STD: string & LHS, const STD: string & RHs ):
STD: logic_error (s), left (LHS), right (RHs ){}
Const STD: String left, right;
Virtual ~ Isbn_mismatch () Throw (){}
};

Sales_item & operator + (const sales_item & LHS, const sales_item RHs)
{
If (! LHS. same_isbn (RHs ))
Throw isbn_mismatch ("ISBN missmatch", LHS. Book (), RHS. Book ());
Sales_item RET (LHS );
RET + RHS;
Return ret;
}

Sales_item Item1, item2, sum;
While (CIN> Item1> item2)
{
Try {
Sun = Item1 + item2;
} Catch (const isbn_mismatch & E)
{
Cerr <E. What () <"Left ISBN is:" <E. Left <"right ISBN is:" <E. Right <Endl;
}
}

 

This ANSI/iso c ++ professional programmer's handbook is like this.

Explicit Constructors
A constructor that takes a single argument is, by default, an implicit conversion operator, which converts its argument
An object of its class (see also Chapter 3, "Operator Overloading"). Examine the following concrete example:
Class string
{
PRIVATE:
Int size;
Int capacity;
Char * Buff;
Public:
String ();
String (INT size); // constructor and implicit conversion Operator
String (const char *); // constructor and implicit conversion Operator
~ String ();
};
Class string has three constructors: a default constructor, a constructor that takes int, and a constructor that
Constructs a string from const char *. The second constructor is used to create an empty string object with
Initial preallocated buffer at the specified size. However, in the case of class string, the automatic conversion is
Dubious. converting an int into a string object doesn' t make sense, although this is exactly what this constructor does.

Consider the following:
Int main ()
{
String S = "hello"; // OK, convert a C-string into a string object
Int NS = 0;
S = 1; // 1 oops, programmer intended to write NS = 1,
}
In the expression S = 1;, the programmer simply mistyped the name of the variable NS, typing s instead. Normally,
The compiler detects the incompatible types and issues an error message. However, before ruling it out, the compiler first
Searches for a user-defined conversion that allows this expression; indeed, it finds the constructor that takes Int.
Consequently, the compiler interprets the expression S = 1; as if the programmer had written
S = string (1 );
You might encounter a similar problem when calling a function that takes a string argument. The following example
Can either be a cryptic coding style or simply a programmer's typographical error. However, due to the implicit
Conversion constructor of class string, it will pass unnoticed:
Int F (string S );
Int main ()
{
F (1); // without a an explicit constructor,
// This call is expanded into: F (string (1 ));
// Was that intentional or merely a programmer's typo?
}
'In order to avoid such implicit conversions, a constructor that takes one argument needs to be declared explicit:
Class string
{
//...
Public:
Explicit string (INT size); // block implicit conversion
String (const char *); // implicit conversion
~ String ();
};
An explicit constructor does not behave as an implicit conversion operator, which enables the compiler to catch
Typographical error this time:
Int main ()
{
String S = "hello"; // OK, convert a C-string into a string object
Int NS = 0;
S = 1; // compile time error; this time the compiler catches the typo
}
Why aren't all constructors automatically declared explicit? Under some conditions, the automatic type conversion is
Useful and well behaved. A good example of this is the third constructor of string:
String (const char *);

The implicit type conversion of const char * To A String object enables its users to write the following:
String S;
S = "hello ";
The compiler implicitly transforms this
String S;
// Pseudo C ++ code:
S = string ("hello"); // create a temporary and assign it to S
On the other hand, if you declare this constructor explicit, you have to use explicit type conversion:
Class string
{
//...
Public:
Explicit string (const char *);
};
Int main ()
{
String S;
S = string ("hello"); // explicit conversion now required
Return 0;
}
Extensive amounts of legacy C ++ code rely on the implicit conversion of constructors. The C ++ Standardization
Committee was aware of that. In order to not make existing code break, the implicit conversion was retained. However,
New Keyword, explicit, was introduced to the specified ageto enable the programmer to block the implicit conversion
When it is undesirable. As a rule, a constructor that can be invoked with a single argument needs to be declared
Explicit. When the implicit type conversion is intentional and well behaved, the constructor can be used as
Implicit conversion operator.

The best online post:

The role of the explicit keyword in C ++

In C ++, if a class has only one constructor parameter, C ++ allows a special way to declare class variables. In this case, a data corresponding to the constructor parameter type can be directly assigned to a class variable, and the compiler automatically performs type conversion during compilation, convert the data corresponding to the constructor parameter type to the class object. If the explicit it modifier is added before the constructor, automatic conversion is disabled. In this case, even if the data corresponding to the constructor parameter type is directly assigned to the class variable, the compiler also reports an error.

The following is an example.

Create the people. cpp file and enter the following content:


/* Humans are human classes, not human -:)*/

Class People
{
Public:

Int age;

Explicit people (int)
{
Age =;
}
};

/* Create a person in three ways "*/

Void Foo (void)
{
People p1 (10); // method 1

People * p_p2 = new people (10); // method 2

People P3 = 10; // method 3
}

This C ++ program defines a class people, including a constructor. This constructor only contains an integer parameter A, which can be used to initialize the age variable when constructing a class.

Then define a function Foo. In this function, we create three 10-year-olds in three ways ". The first is the most common way to declare class variables. The second method is to declare a pointer variable of the People class, dynamically create a people instance in the heap, and assign the address of this instance to p_p2. The third method is what we call a special method. Why? We all know that C/C ++ is a strong type language, and different data types cannot be converted at will. to convert data types, you must perform explicit forced type conversion, here, there is no explicit conversion, and an integer data is directly assigned to the class variable P3.

Therefore, it can be said that an implicit type conversion is performed here, And the compiler automatically converts the data corresponding to the constructor parameter type to the object of this class, therefore, the method 3 is automatically converted by the compiler, and the final implementation method of method 1 is the same.

Don't believe it? When you hear it, you can see it as reality. Let's look at the underlying implementation methods.

In order to make it easier to compare the implementation methods of method 1 and method 3, let's make some modifications to the above Code and Remove Method 2:

Void Foo (void)
{
People p1 (10); // method 1

People P3 = 10; // method 3
}

The reason for removing method 2 is that Mode 2 dynamically creates class instances on the stack, so there will be some additional code impact analysis. After the modification is complete, use the following command to compile people. cpp

$ Gcc-s people. cpp

The "-s" option is the GCC output assembly code. After the command is executed, people. S is generated by default. The key part is as follows:

.globl _Z3foov
.type _Z3foov, @function
_Z3foov:
.LFB5:
pushl %ebp
.LCFI2:
movl %esp, %ebp
.LCFI3:
subl $24, %esp
.LCFI4:
movl $10, 4(%esp)
leal -4(%ebp), %eax
movl %eax, (%esp)
call _ZN6PeopleC1Ei
movl $10, 4(%esp)
leal -8(%ebp), %eax
movl %eax, (%esp)
call _ZN6PeopleC1Ei
leave
ret

Let's look at the things behind ". lcfi4". lines 1-4 are almost the same as lines 5-8. lines 1-4 are the compilation code of method 1, and lines 5-8 are the compilation code of method 3. You may find that 2 and 6 rows are different. One is-4 (% EBP) and the other is-8 (% EBP ), these are the addresses of the class variables P1 and P3 respectively.

C/C ++, a strong type language that cannot be converted at will, is a feature of C ++. Oh, today, I don't seem to want to talk about the features of C ++. Instead, I want to know the role of the explicit keyword?

What is the role of the explicit keyword? This feature is disabled. For example, in the beginning of this article, constructors modified with the explicit keyword will not be automatically converted during compilation, but an error will be reported.

Let's take a look! Modify the Code:

Class People
{
Public:

Int age;

Explicit people (int)
{
Age =;
}
};

Then compile:

$ Gcc-s people. cpp

The compiler immediately reports an error:

People. cpp: In function 'void Foo ()':
People. cpp: 23: Error: request conversion from 'int' to non-standard type 'people'

Do you have any questions?

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.