We can see the simple implementation of a string class in accelerated c ++. We have learned many operators and types to convert them, record them, and forget them...
Str. h
# Include <iostream>
# Include <algorithm>
# Include <cstring>
# Include "Vec. h"
Class Str
{
// You can have the same access permissions as the member functions and place them in any position in the class definition.
Friend std: istream & operator> (std: istream &, Str &);
Public:
Typedef Vec <char >:: size_type;
Str () {}// default constructor
Str (size_type n, char c): data (n, c) {}// a number of connected parameters (number, character) to construct a string of several characters
Str (const char * p) {// constructor that converts a string constant to a string
Std: copy (p, p + std: strlen (p), std: back_inserter (data ));
// Std: cout <"Test 1" <std: endl;
}
// Create a string from the element between iterator B and iterator e
Template <class In> Str (In B, In e ){
Std: copy (B, e, std: back_inserter (data ));
}
// Operator [] index operator
Char & operator [] (size_type I) {return data [I];}
Const char & operator [] (size_type I) const {return data [I];}
// Join operator ① s = s + s1; ② s + = s1
Str & operator + = (const Str & s)
{
Std: copy (s. data. begin (), s. data. end (), std: back_inserter (data ));
Return * this;
}
// Define the size
Size_type size () const {return data. size ();}
Private:
Vec <char> data;
};
// Input-Output Operator
// Judge whether a function is a member function. We have a standard in the previous chapter: Check whether this operation affects the object state.
// Of course, the input operation changes the object. Should I regard it as a member function of Str?
// No. Cause: For a binary operator (such as cin> s), the left operand is always bound to the first parameter,
// For member operator functions, the first parameter is implicitly the object of this member function, so cin> s indicates that
// The member function> in cin, but istream does not have the defined permission. Therefore, if we want to establish cin> s, we must
// Determines that the input operator must be a non-member function. Similarly, the input operator is
Std: istream & operator> (std: istream &, Str &);
Std: ostream & operator <(std: ostream &, const Str &);
Str operator + (const Str &, const Str &); // overload of addition operators (no value is changed, so it is defined outside the class)
Str. cpp
# Include "Str. h"
Using namespace std;
// We call Str: operator [] --> Vec: operator []; similar to calling s. size () --> Vec object size
Ostream & operator <(ostream & OS, const Str & s)
{
For (Str: size_type I = 0; I! = S. size (); ++ I)
{
OS <s [I];
}
Return OS;
}
Istream & operator> (istream & is, Str & s)
{
S. data. clear (); // clear the data www.2cto.com
Char c; // read a single character
While (is. get (c) & isspace (c ))
{// Read all the characters until they are null or the read operation ends.
;
}
If (is) // determines whether the read is complete.
{
Do
{
S. data. push_back (c );
} While (is. get (c )&&! Isspace (c ));
If (is) // determines whether the read is complete.
{
Is. unget (); // At this time, a blank character is read and should be put back into the input stream to prevent the next error
}
}
Return is;
}
// Addition
Str operator + (const Str & s, const Str & t)
{
Str rhs = s;
Rhs + = t;
Return rhs;
}
In addition, two points are described:
1. Binary Operators
+ = Operator, which changes its left operand, so it should be defined as a member of the Str class;
Note: If a class supports type conversion, defining binary operators as non-member functions is a good habit.
If an operator is a member of a class, the left operand of this operator cannot be the result of automatic type conversion.
The left operands of non-member operators and the right operands of any operators follow the same rule as common function parameters: the operands can be of any type, as long as they can be converted to parameter types.
+ Operator. It should be a non-member function. If it is a member function, the left and right operands are asymmetrical (the right operand can be automatically converted to the type, and the left operand cannot)
+ The Return Value of the operator should be the left value and should not be a reference. (C ++ primer explanation: Arithmetic Operators usually generate a new value, which is the calculation result of two operands. It is different from any of the operands, in addition, it is a runtime error to return the reference to that variable in the calculation of a local variable .)
2. conversion operator (from class to other types, opposite to constructor)
Definition: This operator illustrates how to convert objects of this class to the target type. The type conversion operator must be defined as a member of the class. Format: operator target type, such as operator double
In fact, this type conversion operator is used every time we write a circular expression that implicitly detects the value of an istream object. For example, while (cin)
Principle: The standard library defines the type conversion from istream to void * To istream operator void *(). Void * can be converted to the bool type, so the preceding example is true.
Extended: Why does istream not define operator bool to directly convert cin to bool?
Int x; cin <x; (the correct value is cin> x;) in this case, operator bool directly converts cin to bool, And the generated bool value is converted to int type, then shift the value left to x and discard the generated result.
Note: by defining the operation to convert to void * instead of the arithmetic type, the standard library can enable an istream object to be used as a conditional or prevent it from being used as an arithmetic value.
From csqlwy