This is a small C ++ vocabulary that all programmers should understand. The entries below are important enough to ensure that they are fully consistent.
The Declaration tells the compiler about the name and type of something, but it skips some details. The following are declarations:
Extern int X; // object Declaration
STD: size_t numdigits (INT number); // function declaration
Class widget; // class declaration
Template <typename T> // template declaration
Class graphnode; // (see item 42 for info on
// The use of "typename ")
Note: even for built-in types, I prefer to regard integers as an "object". Some people keep the "object" name for user-defined types, but I am not one of them. The return type of the numdigits function is STD: size_t, that is, size_t type in the namespace STD. This namespace is where everything in the C ++ standard library is actually located. However, because the c Standard Library (strictly speaking, from c89) can also be used in C ++, symbols inherited from C (such as size_t) may exist in the global scope, STD, or both, depending on which header file is # pinned ded. In this book, I assume that the C ++ header file is # encoded ded, which is why I replaced size_t with STD: size_t. When the standard library components are involved in the line, I generally do not mention STD, which relies on your approval that everything like size_t, vector, and cout is in STD. In the sample code, I always include STD, because the real Code cannot be compiled without it.
By the way, size_t is only a type of unsigned typedef for C ++ to count something (for example, the number of characters in a string based on char, number of elements in an STL container, and so on ). It is also the type held by the operator [] function of vector, deque, and string. This is a convention to be followed when we define our own operator [] function in item 3.
Each function declaration indicates its signature, that is, its parameters and return types. A function's signature is of the same type. For numdigits, the identification mark (Signature) is STD: size_t (INT), that is, "the function holds an int and returns a STD: size_t ". The official "signature" C ++ definition does not exclude the return type of the function, but in this book, it is more useful to consider the return type as part of the recognition flag.
Definition provides the compiler with details that are omitted during declaration. An object is defined as a place where the compiler sets aside memory for the object. Provides code Ontology for a function or a function template. For a class or a class template, the definition lists the class or template members:
Int X; // object definition
STD: size_t numdigits (INT number) // function definition.
{
// (This function returns
STD: size_t digitssofar = 1; // The number of digits
// In its parameter .)
While (number/= 10 )! = 0) ++ digitssofar;
Return digitssofar;
}
Class widget {
// Class definition
Public:
Widget ();
~ Widget ();
...
};
Template <typename T> // template Definition
Class graphnode {
Public:
Graphnode ();
~ Graphnode ();
...
};
Initialization is the process of setting the first value of an object. For user-defined objects, initialization completes the task through the constructor. The default constructor is a constructor that can be called without any arguments. Such a constructor can be neither a parameter nor a default value for each parameter:
Class {
Public:
A (); // default constructor
};
Class B {
Public:
Explicit B (INT x = 0, bool B = true); // default constructor; see below
}; // For info on "Explicit"
Class C {
Public:
Explicit C (int x); // not a default constructor
};
Here, constructor B and C are declared as explicit ). This is to prevent them from being used for implicit conversions (implicit type conversions), although they can also be used for Explicit conversions ):
Void dosomething (B bobject); // a function taking an object
// Type B
B bobj1; // an object of type B
Dosomething (bobj1); // fine, passes a B to dosomething
B bobj2 (28); // fine, creates a B from the int 28
// (The bool defaults to true)
Dosomething (28); // error! Dosomething takes a B,
// Not an int, and there is no
// Implicit conversion from int to B
Dosomething (B (28); // fine, uses the B constructor
// Explicitly convert (I. e., cast)
// Int to a B for this call. (See
// Item 27 for info on casting .)
Constructor declared as explicit (explicit) is generally more desirable than non-explicit (non-explicit) because they can prevent compiler execution exceptions (often unintentional) type conversion. Unless I have a good reason to allow a constructor to be used for implicit conversions (implicit type conversions), I declare it as explicit ). I hope you can follow the same rule.
Constructor declared as explicit (explicit) is generally more desirable than non-explicit (non-explicit) because they can prevent compiler execution exceptions (often unintentional) type conversion. Unless I have a good reason to allow a constructor to be used for implicit conversions (implicit type conversions), I declare it as explicit ). I hope you can follow the same rule.
Note how I highlight the forced cast in the above sample code. Throughout this book, I use this to highlight the materials you should pay attention. (I also highlight the chapter number, but it is only because I want it to look better .)
Copy constructor is used to initialize another object of the same type as an object, and copy assignment operator) it is used to copy the values of an object to another object of the same type:
Class widget {
Public:
Widget (); // default constructor
Widget (const widget & RHs); // copy constructor
Widget & operator = (const widget & RHs); // copy assignment operator
...
};
Widget W1; // invoke default constructor
Widget W2 (W1); // invoke copy constructor
W1 = W2; // invoke copy
// Assignment operator
When you see something that looks like a value assignment, read it carefully, because "=" can also be used to call the copy constructor in syntax:
Widget W3 = W2; // invoke copy constructor!
Fortunately, the copy constructor is easily distinguished from the copy assignment. If a new object is defined (like W3 in the above line of code), a constructor must be called; it cannot be a value assignment. If no new object is defined (like in the above line "W1 = W2" code), no constructor can be called, so it is a value assignment.
A copy constructor is a very important function because it defines how an object is passed by passing values. For example, consider this:
Bool hasacceptablequality (widget W );
...
Widget awidget;
If (hasacceptablequality (awidget ))...
The parameter W is passed to hasacceptablequality by passing the value. Therefore, in the preceding call, awidget is copied to W. The copy action is executed by the copy constructor of the widget. Passing the value means "calling the copy constructor ". (In any case, passing user-defined types by passing values is usually a bad idea. Passing a reference to a const is usually a better choice .)
STL is a standard template library. As part of the C ++ standard library, STL is dedicated to containers (such as vector, list, set, map, and so on ), iterators (for example, vector <int>: iterator, set <string>: iterator, etc.), algorithms (algorithms) (for example, for_each, find, sort, and other functions. Many related functions are provided through function objects, which act as objects similar to functions. Such objects come from classes that overload operator () -- function call operators --. If you are not familiar with STL, you should have a decent reference manual for future reference when reading this book, because STL is so useful for me that I can't help but use it. Once you use it a little bit, you will feel the same way.
Programmers who come to C ++ from languages like Java or C # may be surprised by the concept of undefined behavior. For various reasons, constructs in C ++ do not have a definite definition: you cannot reliably predict what will happen during runtime. Here are two examples of codes with undefined behaviors:
Int * p = 0; // P is a null pointer
STD: cout <* P; // dereferencing a null pointer
// Yields undefined behavior
Char name [] = "Darla"; // name is an array of Size 6 (don't
// Forget the trailing null !)
Char c = Name [10]; // referring to an invalid array index
// Yields undefined behavior
To emphasize that undefined behaviors are unpredictable and may be annoying, experienced C ++ programmers often say that programs with undefined behaviors can delete your hard disk. This is true: a program with undefined behaviors can delete your hard disk. However, the possibility is not very high. What's more likely is that the program is capricious, sometimes running normally, sometimes completely finished, and sometimes produces incorrect results. Powerful C ++ programmers can avoid undefined behaviors at their best. In this book, I will point out many things you must pay attention.
Another item that may confuse programmers who want to switch from other languages to C ++ is interface ). Both Java and. net use interfaces as a language element, but this is not the case in C ++. When I use an entry "interface", I generally refer to a function identification mark as an accessible element of a class (for example, "Public interface", "protected interface", or "private interface") of a class, or a legal expression required for the type parameter of a template. That is to say, I talk about interfaces as a fairly general design concept.
A client is someone or something that uses the code you write (usually interfaces. For example, the customer of a function is its user: the code snippet that calls the function (or the address that holds it) and the person who writes and maintains the code. Class or template customers are components of software using this class or template, as well as programmers who write and maintain that code. When talking about customers, I generally point to programmers, because programmers are troubled and misled, or they are troubled by bad interfaces. But they do not write code.
You may not be used to thinking about customers, but I will spend a lot of time trying to convince you that you should do your best to make their lives easier. Remember, you are also a customer of software developed by others. Don't you want those people to make things easier for you? In addition, to some extent, you can almost certainly find yourself in the position of your own customers (that is, using the code you write). At this time, you will be happy to keep your mind focused on your customers when developing your interfaces.
I often mask the differences between functions and function templates and between classes and class templates. That is because it is often possible to determine one of the items. Otherwise, I will treat classes, functions, and templates generated by classes and functions differently.
When I mention constructor and destructor in code comments, I sometimes use the abbreviations ctor and dtor.
Naming Conventions naming convention
I tried to select meaningful names for objects, classes, functions, templates, and so on, but the meanings behind some of my names may not appear immediately. For example, the two parameters I particularly like are LHS and RHS. They represent "left-hand side" and "right-hand side" respectively ". I often use them as the parameter names for functions that implement binary operators (for example, operator = and operator. For example, if a and B are rational number objects, and the rational object can be multiplied by a non-member operator * function (this is probably the case described in item 24), the expression
A * B
And function call
Operator * (A, B)
Is equivalent.
I also declared operator * like this:
Const rational operator * (const rational & LHS, const rational & RHs );
You can see that left-hand operand (left-hand operand) A appears as the LHS inside the function, while right-hand operand (right-hand operand) B appears as the RHS.
The left-hand parameter (left-hand argument) of the member function is expressed as the this pointer, so sometimes I use the parameter name RHS separately. You may have noticed this in the declaration of some widget member functions on page 5th (this article introduces the example in the section of the copy constructor-the Translator's note. This reminds me. I often use the widget class in the example. "Widget" does not mean anything. It only uses the name from time to time when I need the name of an example class. It has nothing to do with widgets in the GUI toolkit.
I often follow this rule to name a pointer: a pointer to an object of type T is called PT, "pointer to t ". The following is an example:
Widget * PW; // PW = PTR to widget
Class airplane;
Airplane * pA; // Pa = PTR to airplane
Class gamecharacter;
Gamecharacter * PGC; // PGC = PTR to gamecharacter
I use a similar convention for reference: RW can be considered as a reference to a widget, while RA is a reference to airplane.
When discussing member functions, I occasionally use the name MF.
Threading considerations
As a language, C ++ has no thread concept-in fact, there is no concurrency concept. This is also true for the c ++ standard library. Multi-threaded programming does not exist in the scope of C ++.
And so far they still do. I am committed to making this book based on standard and portable C ++, but I cannot turn a blind eye to the fact that thread safety has become a problem for many programmers. My approach to dealing with the cracks between the standard C ++ and reality is to point out the constructs of a certain C ++ structure) my analysis may cause problems in a multi-threaded environment. This will not make this book a book that uses C ++ for multi-threaded programming. On the contrary, it will make this book quite a C ++ programming book: To a large extent, it will limit itself to single-thread considerations, and acknowledge the existence of multithreading, and try to point out that a thread-aware programmer needs to be especially careful about evaluating the suggestions I provide.
If you are not familiar with multithreaded programming or do not have to worry about it, you can ignore my thread discussion. If you are writing a multi-threaded application or library, remember my comments and use it as the starting point for the problem you need to solve when using C ++.
Tr1 and boost tr1 and boost
You will find the tr1 and boost mentioned throughout the series. Each of them is specifically described in some details, but unfortunately, these are at the end of the entire series. (They are there because they are better. I did try many other places .) If you prefer to start from the beginning rather than the end of the book, the following summary will help you:
· Tr1 ("Technical Report 1") is a specification for new functions added to the C ++ standard library. These functions provide new classes and function templates such as hash tables, reference-counting smart pointers, and regular expressions ), and so on. All tr1 components are nested in namespace tr1 within namespace STD.
· Boost is a portable, peer-reviewed, open-source C ++ library provided by an organization and a website (http://boost.org. Most tr1 functions work based on boost, and until the compiler vendor includes tr1 in their C ++ library release, the boost website is likely to remain the first stop for developers looking for tr1 implementation. Boost provides more things than tr1. In many cases, it is worth learning about.