For high-level applications programming to be effective and convenient, we need libraries. Using just the bare language features makes almost all programming quite painful. That’s true for every general-purpose language. Conversely, giv en suitable libraries just about any programming task can be pleasant.
Procedural programming: This is programming focused on processing and the design of suitable data structures.
Data abstraction: This is programming focused on the design of interfaces, hiding implementation details in general and representations in particular. C++ supports concrete and abstract classes. The facilities for defining classes with private implementation details, constructors and destructors, and associated operations directly support this. The notion of an abstract class provides direct support for complete data hiding.
Object-oriented programming: This is programming focused on the design, implementation, and use of class hierarchies. In addition to allowing the definition lattices of classes, C++ provides a variety of features for navigating class lattices and for simplifying the definition of a class out of existing ones. Class hierarchies provide run-time polymorphism and encapsulation.
Generic programming: This is programming focused on the design, implementation, and use of general algorithms. Here, "general" means that an algorithm can be designed to accept a wide variety of types as long as they meet the algorithm's requirements on its arguments. The template is C++’s main support for generic programming. Templates provide (compiletime) parametric polymorphism. Just about anything that increases the flexibility
Member functions, constructors, destructors, and user-defined assignment provide a clean functional interface to objects as needed by data abstraction and object-oriented programming.
The notion of static types and compile-time type checking is central to effective use of C++.
C++ type-checking and data-hiding features rely on compile-time analysis of programs to prevent accidental corruption of data.
An executable program is created for a specific hardware/system combination; it is not portable, say, from a Mac to a Windows PC. When we talk about portability of C++ programs, we usually mean portability of source code; that is, the source code can be successfully compiled and run on a variety of systems.
C++ is a statically typed language. That is, the type of every entity (e.g., object, value, name, and expression) must be known to the compiler at its point of use. The type of an object determines the set of operations applicable to it.
For example, the declaration
int inch;
specifies that inch is of type int; that is, inch is an integer variable.
A declaration is a statement that introduces a name into the program. It specifies a type for the named entity.
A type defines a set of possible values and a set of operations (for an object).
数据结构亦是相同的定义:数组元素之间的关系,及作用于数据元素之上的操作,如增、删、改、查、遍历等。
An object is some memory that holds a value of some type.
A value is a set of bits interpreted according to a type.
A variable is a named object.
Having the data specified separately from the operations on it has advantages, such as the ability to use the data in arbitrary ways. However, a tighter connection between the representation and the operations is needed for a user-defined type to have all the properties expected of a "real type." In particular, we often want to keep the representation inaccessible to users, so as to ease use, guarantee consistent use of the data, and allow us to later improve the representation. To do that we have to distinguish between the interface to a type (to be used by all) and its implementation (which has access to the otherwise inaccessible data). The language mechanism for that is called a class. A class is defined to have a set of members, which can be data, function, or type members. The interface is defined by the public members of a class, and private members are accessible only through that interface.
A program built out of a well chosen set of classes is far easier to understand and get right than one that builds everything directly in terms of the built-in types. In particular, classes are often what libraries offer.
C++'s support for abstraction and resource management。
Essentially all language facilities beyond the fundamental types, operators, and statements exist to help define better classes or to use them more conveniently. By "better," I mean more correct, easier to maintain, more efficient, more elegant, easier to use, easier to read, and easier to reason about. Most programming techniques rely on the design and implementation of specific kinds of classes. The needs and tastes of programmers vary immensely. Consequently, the support for classes is extensive.
class Container { public: virtual double& operator[](int) = 0; // pure virtual function virtual int size() const = 0; // const member function (§3.2.1.1) virtual ~Container() {} // destructor (§3.2.1.2) };
This class is a pure interface to specific containers defined later. The word virtual means "may be redefined later in a class derived from this one." Unsurprisingly, a function declared virtual is called a virtual function. A class derived from Container provides an implementation for the Container interface. The curious =0 syntax says the function is pure virtual; that is, some class derived from Container must define the function. Thus, it is not possible to define an object that is just a Container; a Container can only serve as the interface to a class that implements its operator[]() and size() functions. A class with a pure virtual function is called an abstract class.
No significant program is written in just a bare programming language. First, a set of libraries is developed. These then form the basis for further work. Most programs are tedious to write in the bare language, whereas just about any task can be rendered simple by the use of good libraries.
A resource is something that must be acquired and later (explicitly or implicitly) released. Examples are memory, locks, sockets, thread handles, and file handles. For a long-running program, failing to release a resource in a timely manner ("a leak") can cause serious performance degradation and possibly even a miserable crash.
unique_ptr to represent unique ownership
shared_ptr to represent shared ownership
In low-level code, we occasionally need to store or pass along an address of a memory location without actually knowing what type of object is stored there. A void* is used for that. You can read void* as "pointer to an object of unknown type."
void x; // error : there are no void objects
void& r; // error : there are no references to void
void f(); // function f does not return a value
void* pv; // pointer to object of unknown type
When declaring a function, you must specify the type of the value returned. Logically, you would expect to be able to indicate that a function didn’t return a value by omitting the return type. Howev er, that would make a mess of the grammar. Consequently, void is used as a "pseudo return type" to indicate that a function doesn’t return a value.
It is used either to specify that a function does not return a value or as the base type for pointers to objects of unknown type.
A floating-point number is an approximation of a real number represented in a fixed amount of memory.
Before a name (identifier) can be used in a C++ program, it must be declared. That is, its type must be specified to inform the compiler what kind of entity the name refers to.
As can be seen from these examples, a can do more than simply associate a type with a name. Most of these declarations are also definitions. A definition is a declaration that supplies all that is needed in a program for the use of an entity. In particular, if it takes memory to represent something, that memory is set aside by its definition. A different terminology deems declarations parts of an interface and definitions parts of an implementation.
prefix & lvalue reference
prefix && rvalue reference
type:
fundermental types;
new user-defined types;
aliases;
typedef char* Pchar;
using Pchar = char*; // pointer to character
typedef int(* PF)(double);
using PF = int(*)(double); // pointer to function taking a double and returning an int
sizeof("Bohr")==5
The type of a string literal is "array of the appropriate number of const characters," so "Bohr" is of type const char[5].
char* p = "Plato"; // error, but accepted in pre-C++11-standard code
p[4] = 'e'; // error : assignment to const
If we want a string that we are guaranteed to be able to modify, we must place the characters in a non-const array:
char p[] = "Zeno"; // p is an array of 5 char
p[0] = 'R'; // OK
A string literal is statically allocated so that it is safe to return one from a function. For example:
const char* error_message(int i) { // ... return "range error"; }
string var {"Cambridge"};
string f();
string& r1 {var}; // lvalue reference, bind r1 to var (an lvalue)
string& r2 {f()}; // lvalue reference, error : f() is an rvalue
string& r3 {"Princeton"}; // lvalue reference, error : cannot bind to temporar y
string&& rr1 {f()}; // rvalue reference, fine: bind rr1 to rvalue (a temporar y)
string&& rr2 {var}; // rvalue reference, error : var is an lvalue
string&& rr3 {"Oxford"}; // rr3 refers to a temporar y holding "Oxford"
const string cr1& {"Harvard"}; // OK: make temporar y and bind to cr1
Often, the compiler must introduce an object to hold an intermediate result of an expression. For example, for v=x+y*z the result of y*z has to be put somewhere before it is added to x. For built-in types, this is all handled so that a temporary object (often referred to as just a temporary) is invisible to the user. However, for a user-defined type that holds a resource knowing the lifetime of a temporary can be important. Unless bound to a reference or used to initialize a named object, a temporary object is destroyed at the end of the full expression in which it was created. A full expression is an expression that is not a subexpression of some other expression.
Integral and floating-point types can be mixed freely in assignments and expressions. Wherever possible, values are converted so as not to lose information. Unfortunately, some valuedestroying ("narrowing") conversions are also performed implicitly. A conversion is value-preserving if you can convert a value and then convert the result back to its original type and get the original value. If a conversion cannot do that, it is a narrowing conversion.
y=++x is equivalent to y=(x=x+1). The value of x++, however, is the old value of x. For example, y=x++ is equivalent to y=(t=x,x=x+1,t), where t is a variable of the same type as x.
The semantics of argument passing are identical to the semantics of copy initialization. Argument types are checked and implicit argument type conversion takes place when necessary.
The number of errors in code correlates strongly with the amount of code and the complexity of the code. Both problems can be addressed by using more and shorter functions. Using a function to do a specific task often saves us from writing a specific piece of code in the middle of other code; making it a function forces us to name the activity and document its dependencies. Also, function call and return saves us from using error-prone control structures, such as gotos and continues. Unless they are very regular in structure, nested loops are an avoidable source of errors (e.g., use a dot product to express a matrix algorithm rather than nesting loops;).
The most basic advice is to keep a function of a size so that you can look at it in total on a screen. Bugs tend to creep in when we can view only part of an algorithm at a time. For many programmers that puts a limit of about 40 lines on a function. My ideal is a much smaller size still, maybe an average of 7 lines.
In addition to specifying a name, a set of arguments, and a return type, a function declaration can contain a variety of specifiers and modifiers. In all we can have:
The name of the function; required
The argument list, which may be empty (); required
The return type, which may be void and which may be prefix or suffix (using auto); required
inline, indicating a desire to have function calls implemented by inlining the function body
constexpr, indicating that it should be possible to evaluate the function at compile time if given constant expressions as arguments
noexcept, indicating that the function may not throw an exception
A linkage specification, for example, static >[[noreturn]], indicating that the function will not return using the normal call/return mechanism
In addition, a member function may be specified as:
virtual, indicating that it can be overridden in a derived class
override, indicating that it must be overriding a virtual function from a base class
final, indicating that it cannot be overriden in a derived class
static, indicating that it is not associated with a particular object
const, indicating that it may not modify its objec
How do we choose among the ways of passing arguments? My rules of thumb are:
[1] Use pass-by-value for small objects.
[2] Use pass-by-const-reference to pass large values that you don’t need to modify.
[3] Return a result as a return value rather than modifying an object through an argument.
[4] Use rvalue references to implement move and forwarding.
[5] Pass a pointer if "no object" is a valid alternative (and represent "no object" by nullptr).
[6] Use pass-by-reference only if you have to.
The "when you have to" in the last rule of thumb refers to the observation that passing pointers is often a less obscure mechanism for dealing with objects that need modification than using references.
A program can terminate in several ways:
[1] By returning from main()
[2] By calling exit()
[3] By calling abort()
[4] By throwing an uncaught exception
[5] By violating noexcept
[6] By calling quick_exit()
In addition, there are a variety of ill-behaved and implementation-dependent ways of making a program crash (e.g., dividing a double by zero).
If a program is terminated using the standard-library function exit(), the destructors for constructed static objects are called. However, if the program is terminated using the standard-library function abort(), they are not. Note that this implies that exit() does not terminate a program immediately. Calling exit() in a destructor may cause an infinite recursion.
By default, a class provides:
A default constructor: X()
A copy constructor: X(const X&)
A copy assignment: X& operator=(const X&)
A move constructor: X(X&&)
A move assignment: X& operator=(X&&)
A destructor: ~X()
From Simula, C++ borrowed the ideas of classes and class hierarchies.
Interface inheritance is often referred to as run-time polymorphism (or dynamic polymorphism). In contrast, the uniform use of classes not related by inheritance provided by templates (§3.4, Chapter 23) is often referred to as compile-time polymorphism (or static polymorphism).
Virtual functions overcome the problems with the type-field solution by allowing the programmer to declare functions in a base class that can be redefined in each derived class.
A dynamic_cast can cast from a polymorphic virtual base class to a derived class or a sibling class. A static_cast does not examine the object it casts from。
Construction is bottom-up, destruction is top-down, and a class object is an object to the extent that it has been constructed or destroyed. This order is necessary to ensure that an object is not accessed before it has been initialized. It is unwise to try to access base and member objects early or out of order through "clever" pointer manipulation.
unique_ptr to represent exclusive ownership
shared_ptr to represent shared ownership
weak_ptr to break loops in circular shared data structures
A unique_ptr cannot be copied (has no copy constructor or copy assignment). However, it can be moved.
You need a C++ compiler and linker that can generate code for your windowing environment (Windows, XWindow, MacOS, ...). Windowed programs do not generally use the console to communicate with the user. They use a set of functions or classes to manipulate windows instead, which are specific to each environment. Anyway, the same principles apply both for console and windowed programs, except for communicating with the user.
Visual C++ is the name of a C++ compiler with an integrated environment from Microsoft. It includes special tools that simplify the development of large applications as well as specific libraries that improve productivity. The use of these tools is generally known as visual programming. Other manufacturers also develop these types of tools and libraries, like Borland C++, Visual Age, etc...
An executable program is created for a specific hardware/system combination. When we talk about portability of C++ programs, we usually mean protability of source ocde.
The ISO C++ standard defines two kinds of entities:
1 Core language features, such as built-in types and loops;
2 standard-library component, such as containers and I/O operations.
Essentially all executable code is placed in functions and called directly or indirectly form main(), we can compose fnctions forces us to name the activity and document is dependencies.
Every name and every expression has a type that determined the operations that may be performed on it.
A type defines a set possible values and a set of operations.
an object is some memory that holds a value of some type.
A value is a set of bits interpreted according to a type.
A variable is a name object.
Each fundamental type corresponds directly to hardware facilities and has a fixed size that determines the ranges of values that can be store in it.
C++ provides a conventional set of statements for expressing selection and looping.
Type built out of the built-in type using C++'s abstraction mechanisms are called user-defined types. they are refered to as classes and enumerations.
Having the data specified separately from the operations on it has advantages such as the bility to use the data in arbitrary ways. However, a tighter connection between the representation and the operations is need for a user-defined of a "real type." In particular, we often want to keep the representation inaccessible to users.
A union is a struct in which all members are allocated at the same same address so that the union occupies only as much space as its largest member. Naturally, a union can hold a value for only one member at a time.
Use enumerations to represent sets of name constants that enumerate the value.
A struct is simply a class with its members public by default.
organize related data into structures.
a set of data related data and a set of operations about those data.
No significant program is written in just a bare programming language. First, a set of libraries is developed. These then form the basis for further work.
Statements are analogous to sentences in a natural language. In C++ there are simple statements that execute a single task and compound statements that consist of a block of statements that execute as a unit. Like most languages, C++ provides statements for conditional execution and loops that repeatedly execute the same body of code.
语句类似于自然语言中的句子。C++ 语言既有只完成单一任务的简单语句,也有作为一个单元执行的由一组语句组成的复合语句。和大多数语言一样,C++ 也提供了实现条件分支结构的语句以及重复地执行同一段代码的循环结构。
By default, statements are executed sequentially. Except for the simplest programs, sequential execution is inadequate. Therefore, C++ also defines a set of flow-of-control statements that allow statements to be executed conditionally or repeatedly. The if and switch statements support conditional execution. The for, while, and do while statements support repetitive execution. These latter statements are often referred to as loops or iteration statements.
通常情况下,语句是顺序执行的。但是,除了最简单的程序外,只有顺序执行往往并不足够。为此,C++ 定义了一组控制流语句,允许有条件地执行或者重复地执行某部分功能。if 和 switch 语句提供了条件分支结构,而 for、while 和 do while 语句则支持重复执行的功能。后几种语句常称为循环或者迭代语句。
A compound statement, usually referred to as a block, is a (possibly empty) sequence of statements surrounded by a pair of curly braces. A block is a scope. Names introduced within a block are accessible only from within that block or from blocks nested inside the block. As usual, a name is visible only from its point of definition until the end of the enclosing block.
复合语句,通常被称为块,是用一对花括号括起来的语句序列(也可能是空的)。块标识了一个作用域,在块中引入的名字只能在该块内部或嵌套在块中的子块里访问。通常,一个名字只从其定义处到该块的结尾这段范围内可见。
Compound statements can be used where the rules of the language require a single statement, but the logic of our program needs to execute more than one. For example, the body of a while or for loop must be a single statement. Yet, we often need to execute more than one statement in the body of a loop. We can do so by enclosing the statements in a pair of braces, thus turning the sequence of statements into a block.
复合语句用在语法规则要求使用单个 语句但程序逻辑却需要不止一个语句的地方。例如,while 或 for 语句的循环体必须是单个语句。然而,大多数情况都需要在循环体里执行多个语句。因而可使用一对花括号将语句序列括起来,使其成为块语句。
One advantage of limiting the scope of variables defined within a control statement to that statement is that the names of such variables can be reused without worrying about whether their current value is correct at each use. If the name is not in scope, then it is impossible to use that name with an incorrect, leftover value.
对于在控制语句中定义的变量,限制其作用域的一个好处是,这些变量名可以重复使用而不必担心它们的当前值在每一次使用时是否正确。对于作用域外的变量,是不可能用到其在作用域内的残留值的。
Deeply nested if else statements can often be correct syntactically and yet not correctly reflect the programmer's logic. For example, mistaken else if matchings are more likely to pass unnoticed. Adding a new condition and associated logic or making other changes to the statements is also hard to get right. A switch statement provides a more convenient way to write deeply nested if/else logic.
深层嵌套的 if else 语句往往在语法上是正确的,但逻辑上去却没有正确地反映程序员的意图。例如,错误的 else if 匹配很容易被忽略。添加新的条件和逻辑关系,或者对语句做其他修改,都很难保证正确。switch 语句提供了一种更方便的方法来实现深层嵌套的 if/else 逻辑。
The other circumstance in which reference parameters are useful is when passing a large object to a function. Although copying an argument is okay for objects of built-in data types and for objects of class types that are small in size, it is (often) too inefficient for objects of most class types or large arrays. Some class types cannot be copied. By using a reference parameter, the function can access the object directly without copying it.
在向函数传递大型对象时,需要使用引用形参,这是引用形参适用的另一种情况。虽然复制实参对于内置数据类型的对象或者规模较小的类类型对象来说没有什么问题,但是对于大部分的类类型或者大型数组,它的效率(通常)太低了;某些类类型是无法复制的。使用引用形参,函数可以直接访问实参对象,而无须复制它。
Two functions that appear in the same scope are overloaded if they have the same name but have different parameter lists.
出现在相同作用域中的两个函数,如果具有相同的名字而形参表不同,则称为重载函数。
Implicit parameter of a member function. this points to the object on which the function is invoked. It is a pointer to the class type. In a const member function the pointer is a pointer to const.
成员函数的隐式形参。this 指针指向调用该函数的对象,是指向类类型的指针。在 const 成员函数中,该指针也指向 const 对象。
cout (pronounced see-out) an ostream object that writes to the standard output
cout(发音为 see-out):写到标准输出的 ostream 对象。
operator >>, which is used to read input from an istream object
>> 操作符,用于从 istream 对象中读入输入。
operator <<, which is used to write output to an ostream object
<< 操作符,用于把输出写到 ostream 对象中。
cerr (pronounced see-err) an ostream object that writes to the standard error. cerr is usually used for program error messages.
cerr(发音为 see-err):输出标准错误的 ostream 对象。cerr 常用于程序错误信息。
Sales_item operator+(const Sales_item&, const Sales_item&);
声明了加号操作符,可用于将两个 Sales_item 对象“相加”并获得一个 Sales_item 对象的副本。
Overloaded Operators Must Have an Operand of Class Type
重载操作符必须具有一个类类型操作数
Precedence and Associativity Are Fixed
操作符的优先级、结合性或操作数目不能改变。
Short-Ciruit Evaluation Is Not Preserved
不再具备短路求值特性
smart pointer(智能指针)
A class that defines pointer-like behavior and other functionality, such as reference counting, memory management, or more thorough checking. Such classes typically define overloaded versions of dereference (operator*) and member access (operator->).
一个类,定义了指针式行为和其他功能,如,引用计数、内存管理、更全面的检查等。这种类通常定义了解引用操作符(operator*)和成员访问操作符(operator->)的重载版本。
The ideas of inheritance and dynamic binding are simple but powerful. Inheritance lets us write new classes that share behavior with their base class(es) but redefine that behavior as needed. Dynamic binding lets the compiler decide at run time which version of a function to run based on an object's dynamic type. The combination of inheritance and dynamic binding lets us write type-independent programs that have type-specific behavior.
继承和动态绑定的思想,简单但功能强大。继承使我们能够编写新类,新类与基类共享行为但重定义必要的行为。动态绑定使编译器能够在运行时根据对象的动态类型确定运行函数的哪个版本。继承和动态绑定的结合使我们能够编写具有特定类型行为而又独立于类型的程序。
The function header describe the interface bewteen called function and calling function.
The main() function header describes the interface between program and the operating system.
The augument is the value let calling function assign to the parameter of the called function.
A return statement sends a value from a called function back to the called function, also the type of return value must be consistent with the return type of called function.
As computers have grown more powerful, computer programs have become larger and more complex. In response to these conditions, computer languages have evolved so that it's easier to manage the programming process. The C language incorporated features such as control structures and functions to better control the flow of a program and to enable a more structured, modular approach. To these tools C++ adds support for object-oriented programming and generic programming. This enables even more modularity and facilitates the creation of reusable code, which waves time and increases program reliability.
The popularity of C++ has resulted in a large of number of implementations for many computing platforms; The C++ ISO standards(C++98/03 and c++11) provide a basis for keeping these many implementations mutually compatible. The standards establishes the features the lanugage should have, the behavior the lanugage should display, and a standard language of functions, classes, and templates. The standards supports the goal of a portable language across different computing platforms and different implementations of the language.
To create a C++ program, you create one or more source files containing the program as expressed in the C++ language. These are text files that must be compiled and linked to produce the machine-language files that constitute executable programs. These tasks are often accomplished in an IDE that provides a text editor for creating the source files, a compiler and a linker for producing executable files, and other resources, such as project management and debugging capabilities. But the same tasks can also be performed in a command-line environment by invoking the appropriate tools individually.
Simple Variables
int num;
num = 5;
These statements tell the program that it is storing an integer and that the name num represents the integer's value, 5 in this case, the program locates a chunk of memory large enough to hold an integer, notes the location, and copies the value 5 into the location. You then can use num later in your program to access that memory location. These statements don't tell you where in memory the value is stored, but the program does keep track of that information, too. Indeed, you can use the & operator to retrieve num's address in memory. You'll learn about that operator when you investigate a second strategy for indentifying data-using pointers.
cout << typeid(ptr[1]).name() << endl;
The char type: characters and small integers
char ch;
cin >>ch; // input a letter M
cout <<ch;
On input, cin converts the keystroke input M to the value 77. On output, cout converts the value 77 to the displayed character M.
Characters are represented by their numeric codes. The I/O system determines whether a code is interpreted as a character or as a number.
From smallest to largest, the integer types are bool, char, signed char, unsigned char, short, unsigned short, int, unsigned int, long, unsigned long, and, with C++11, long long, and unsigned long long. There is also a wchar_t type whose placement in this sequence of size depends on the implementation.
C-style strings: a arrays of chars, the last character of every strings is the null character,written \0.
char bird[11] = "cheeps"; // the \0 is understood
char fish[] = "bubbles"; //let the compiler count
A string is a series of characters stored in consecutive bytes of memory. C++ has two ways of dealing with strings. The first, taken from C and often called a C-style string, then, an alternative method based on a string class library.
The string class definition hides the array nature of a string and lets you treat a string much like an ordinary variable.
C-style strings use functions library to process string with header file
The string class, is more convenient and safe than using an array. For example, you can't simply assign one array to another, but you can assign one string object to another.
The string class simplifies combining strings. You can use the + operator to add two string objects together and the += operator to take on a string to the end of an existing string object. (C-style string use strcat() to combine two strings)
The special relationship between arrays and pointers extends to c-style string.
const char * bird = "wren"; // bird holds address of string
the string "wren" is a literal string, the first address is assigned to a point bird, and the literal string is a constant, so bird must be a pointer constant, a pointer, point to a constant.
"wren"作为字面有单独的内存空间,储存在内存的数据段,并返回一个地址。(字符串以外的字面量由代码直接表示,不另外开辟内存空间。)
For built-in types, the information about operations is built in to the compiler. But when you define a user-defined type in C++, you have to pvovide the same kind of information yourself. In exchange for this extra work, you gain the power and flexibility to custom fit new data types to match real-world requirements.
Using classes is a good way to implement what computer scientiests describe as abstract data types(ADTs). As the name suggests, an ADT describes a data type in a general fashion without bringing in language or implementation details.
Friends mechanism let nonemember function access private data.
A derived class has some special relationships with the base class. One,which you've just seen, is that a derived-class object can use base-class methods.
Two other important relationships are that a base-class pointer can point to a derived class object without an explicit type cast and that a base-class reference can refer to a derived-class object without an explicit type cast.
In general, a class defines what data is used to represent an object and the operations that can be performed on that data.
通常,类定义了用来表示对象的数据以及可以对该数据执行的操作。
new and delete enable you to allocate memory in one function and free it in another.Thus, the lifetime of the data is not tied arbitrarily to the life of the program or the life of a function.
The new opertor lets you request memory for a data object while a program is running. The operator returns the address of the memory it obtains, and you can assign that address to a pointer.
C++ offers many choiced for storing data in memory. You have choices for how long data remains in memory(storage duration) and choices for which parts of a program have access to data(scope and linkage). You can allocate memory dynamically by using new.
Many programs read text input or text files character-by-character. The istream class provides several ways to do this.
Function templates automate the process of overloading functions. You define a function by using a generic type and a particular algorithm, and the compiler generates appropriate function definitions for the particular argument types you use in a program.
Objects that have members pointing to memory allocated by new also have problems with initializing one object to another or assigning one object to another. By default, C++ uses memberwise initialization and assignment, which means that the initialized or the assigned-to object to another winds up with exact copies of the original object's members. If an original member points to a block of data, the copy member points to the same block. When the program eventually deletes the two objects, the class destructor attempts to delete the same block of memory twice, which is an error. The solution is to define a special copy constructor that redefines initialization and to overload the assignment operator. In each case, the new definition should create duplicates of any pointed-to data and have the new object point to the copies. That way, both the old and the new objects refer to separate but identical data, with no overlap. The same reasoning applies to defining an assignment operator. In each case, the goal is to make a deep copy-that is, to copy the real data and not just pointers to that data.
The C++ stream library in C++ supports the reading and writing of data files. You can read the file character by character using the get methods, line by line using the getline method, or as formatted data using the >> extraction operator.
The
You can think of a text file as a sequence of characters stored in a permanent medium and identified by a file name. The name of the file and the character it contains have the same relationship as the name of a variable and its contents.
Because the stream libraries predate the introduction of the string class, so open method expects a C-style string as the file name.
With the exception of Stack and Queue, all collection classes support the foreach pattern, which makes it easy to cycle through the elements of the collection.
Programmers who create a library are its implementers; programmers who make use of one are called its clients. The connection between the implementer and the client is called an interface. interfaces typically export functions, types, and constants, which are collectively known as interface entries.
In c++, interface are stored in header file, which typically end with a .h suffix. Every interface should include several lines of interface boilerplate to ensure that the compiler reads the interface only once.
When you design an interface, you must balance several criteria. Well-designed interfaces are unified, simple, sufficient, general, and stable.
C++ is designed to be a compiled language, meaning that it is generally translated into machine language that can be understood directly by the system, making the generated program highly efficient. For that, a set of tools are needed, known as the development toolchain, whose core are a compiler and its linker.
a = (b=3, b+2);///a=5
cin extraction always considers spaces (whitespaces, tabs, new-line...) as terminating the value being extracted, and thus extracting a string means to always extract a single word, not a phrase or an entire sentence.
To get an entire line from cin, there exists a function, called getline, that takes the stream (cin) as first argument, and the string variable as second. For example:getline (cin, mystr);
a class can include a special function called its constructor, which is automatically called whenever a new object of this class is created, allowing the class to initialize member variables or allocate storage.
Like any other function, a constructor can also be overloaded with different versions taking different parameters: with a different number of parameters and/or parameters of different types. The compiler will automatically call the one whose parameters match the arguments。
When a constructor is used to initialize other members, these other members can be initialized directly, without resorting to statements in its body. This is done by inserting, before the constructor's body, a colon (:) and a list of initializations for class members. For example, consider a class with the following declaration:
class Rectangle { int width,height; public: Rectangle(int,int); int area() {return width*height;} };
The constructor for this class could be defined, as usual, as:
Rectangle::Rectangle (int x, int y) { width=x; height=y; }
But it could also be defined using member initialization as:
Rectangle::Rectangle (int x, int y) : width(x) { height=y; }
Or even:
Rectangle::Rectangle (int x, int y) : width(x), height(y) { }
Note how in this last case, the constructor does nothing else than initialize its members, hence it has an empty function body.
For members of fundamental types, it makes no difference which of the ways above the constructor is defined, because they are not initialized by default, but for member objects (those whose type is a class), if they are not initialized after the colon, they are default-constructed.
The function operator+ of class CVector overloads the addition operator (+) for that type. Once declared, this function can be called either implicitly using the operator, or explicitly using its functional name:
c = a + b;
c = a.operator+ (b);
Destructors fulfill the opposite functionality of constructors: They are responsible for the necessary cleanup needed by a class when its lifetime ends. The classes we have defined did not allocate any resource and thus did not really require any clean up.
But now, let's imagine that the class in the last example allocates dynamic memory to store the string it had as data member; in this case, it would be very useful to have a function called automatically at the end of the object's life in charge of releasing this memory. To do this, we use a destructor.
If the function is used inside only a particular file, you generally declare and define the function in the source file. If the function is for use by other modules or files, you generally put the declaration in a header file and the definition in a source file.
Arrays hold a series of values, all of the same type, each of which can be accessed by its position in the array. In C++, you must provide the size of the array when the array is declared. You cannot give a variable as the size—it must be a constant, or a constant expression (constexpr).
cout << "hello" << endl;
“hello” is a string literal because it is written as a value, not a variable. String literals are actually stored in a read-only part of memory. This allows the compiler to optimize memory usage by reusing references to equivalent string literals. That is, even if your program uses the string literal “hello” 500 times, the compiler is allowed to create just one instance of hello inmemory. This is called literal pooling.
OOP is based on the notion that you should divide your program not into tasks, but into models of physical objects. While this seems abstract at first, it becomes clearer when you consider physical objects in terms of their classes, components, properties, and behaviors.
Object-oriented languages provide a number of mechanisms for dealing with such relationships between objects. The tricky part is to understand what the relationship actually is. There are two main types of object relationships—a has-a relationship(combination) and an is-a relationship.
The Is-A Relationship (Inheritance)
The key to abstraction is effectively separating the interface from the implementation. The implementation is the code you're writing to accomplish the task you set out to accomplish. The interface is the way that other people use your code. In C, the header file that describes the functions in a library you've written is an interface. In object-oriented programming, the interface to a class is the collection of publicly accessible properties and methods. A good interface contains only public methods.Properties of a class should never be made public but can be exposed through public methods,also called getters and setters.
Preventing Inheritance C++ allows you to mark a class as final, which means trying to inherit from it will result in a compilation error. A class can be marked as final with the final keyword right behind the name of the class. For example, the following Base class is marked as final: class Base final{};
Header files are a mechanism for providing an abstract interface to a subsystem or piece of code. One of the trickier parts of using headers is avoiding multiple includes of the same header file and circular references.
If you are familiar with the C language, you have undoubtedly used printf() and scanf(). As I/O mechanisms, printf() and scanf() are certainly flexible. Through escape codes and variable placeholders, they can be customized to read in specially formatted data, or output any value that the formatting codes permit, which is currently limited to integer/character values, floating point values, and strings. However, printf() and scanf() falter on other measures of good I/O systems. They do not handle errors particularly well, they are not flexible enough to handle custom data types, and in an object-oriented language like C++, they are not at all object oriented.
In C++, there are three common sources and destinations for streams: console, file, and string.
The cout stream is the built-in stream for writing to the console, or standard output. You can “chain” uses of << together to output multiple pieces of data. This is because the << operator returns a reference to the stream as its result so you can immediately use << again on the same stream.
Just like output streams, input streams have several methods that allow a lower level of access than the functionality provided by the more common >> operator.
When dealing with the file system, it is especially important to detect and handle error cases. The file you are working with could be on a network file store that just went offline, or you may be trying to write to a file that is located on a disk that is full. Maybe you are trying to open a file for which the current user does not have permissions. Error conditions can be detected by using the standard error handling mechanisms described earlier.
The only major difference between output file streams and other output streams is that the file stream constructor can take the name of the file and the mode in which you would like to open it. The default mode is write, ios_base::out, which starts writing to a file at the beginning, overwriting any existing data. You can also open an output file stream in append mode by specifying the constant ios_base::app as second argument to the file stream constructor.
Streams provide a flexible and object-oriented way to perform input and output.
C++ provides a more refined method of input and output through a mechanism known as streams. Streams are a flexible and object-oriented approach to I/O.
More generally, all streams can be viewed as data chutes. Streams vary in their direction and their associated source or destination. For example, the cout stream that you are already familiar with is an output stream, so its direction is “out.” It writes data to the console so its associated destination is “console.” The c in cout does not stand for “console” as you might expect, but stands for “character” as it's a character- based stream. There is another standard stream called cin that accepts input from the user. Its direction is “in,” and its associated source is “console.” As with cout, the c in cin stands for "character". Both cout and cin are predefined instances of streams that are defined within the std namespace in C++.