The Str class represents null terminated strings. I wrote the code for this class before there was a
std::string class. You should, of course, use the std::string class. However, Str is a really nice
tool to illustrate how value types are created.
Value types are instances of classes that can be copied and assigned. When a copy or assignment operation
completes, there are two unique instances of STR, each with the same state values. But these states are
independent. Should the destination of a copy or assignment change its state, that does not affect, in any
way the state of the source Str instance.
This is achieved by careful implementation of copy, move, and assignment operations. Each of the items,
below, shows how to implement every one of the Str class methods and a couple of global functions associated
with the class, e.g., Str insertion and extraction operators.
For each method in the Str class, declared in the figure at the right, we show, in the following items,
how to declare, implement, and invoke the method.
Click on body of image to expand. Click on top bar to contract.
2.0 Str Methods
Str Default Constructor
Str default constructor initializes an instance of Str with no arguments. This might be used, for example,
to construct an array of Str instances.
Str Copy Constructor
Copy constructors play an important role in developing value types, since copying is an essential feature
for them. Every time we pass a method or function argument by value, we make a copy of the instance on the
functions stack frame. The same is true for return by value, and any code that explicitly invokes a copy.
Str Move Constructor
Move constructors allow the compiler to avoid making copies when the source of the copy is a temporary
instance. A properly designed move constructor will take ownership of the temporary's state, possibly
invalidating the temporary object. That is not a problem as long as a move is the last thing that happens
before the temporary goes out of scope.
Str Promotion Constructor
Promotion constructors take a single argument of some other type, causing a conversion of the source type
to the destination type. Essentially the promotion constructor is just using information contained in the
source to build a new Str instance. For STR, we define a promotion from literal strings to Str instances.
Str Destructor
Every class must have a destructor, either defined by the class, or implemented by the compiler. For STR
instances, that just deallocates their character storage from the native heap.
Str Copy Assignment Operator
Copy assignment changes the state of an existing instance to match the state of a source instance.
After copy assignment no changes have been made to the source. The states of the two instances,
source and destination, have the same values but are stored independently.
Str Move Assignment Operator
The idea of move assignment is very like move construction. The only significant difference is that
with move construction we are building a new instance, while with move assignment we transfer ownership
of the source's state to the destination. When compiling an assignment expression, the compiler
will use copy assignment if the source is a named object that will remain in scope. If the source is
a temporary object, the compiler will use move assignment.
Str Index Operator
An index operator is used to access one item of a collection, usually stored as a private member
of the class. For non-const indexers, the index operator can be used to both read and write the item.
Str Const Index Operator
A const index operator is used to access one item of a collection for reading, usually stored as a private member
of the class. This allows indexing a const instance of a class that provides this operator.
Str Append a Character
The character append operation is a bit complicated, because the Str instance may, or may not, have unallocated
memory to store the character in its char array. We have to check the space available and based on the result
either store in the original array, or create a larger temporary array, copy the original characters, append the
new one, deallocate the original array, and attach the new one to the instance.
Str Append a String
This operation is very similar to the preceeding one, but now we check for space for the string.
Str Addition Operator
Having implemented the Append operations, implementation of the Addion operator is almost trivial.
Str Cast Operator
Casts create an instance of a new type based on information stored in the source type.
For Str instances that simply returns a const pointer to its internal character storage,
e.g., it returns a const literal string.
Str Insertion Operator
Insertion operators have to be implemented as global functions. For STR, the insertion simply
streams its characters to the output stream, specified in its calling parameters.
Str Extraction Operator
Extraction could be complicated because we are streaming in from a source for which we have no
size information. However, because we already implemented the character append operation, which
takes care of ensuring adequate storage, we simply append characters from the source stream.
Coersions
Coercions happen when a compiler applies a promotion constructor or cast operator to
create an instance of a different type than the source of the coercion.
Binary Operator Model
Binary operators can be defined either as class members or global functions. This item
discusses the syntax for doing that.
Expression Model
When the compiler scans a C++ expression it looks for type mismatches. If it finds any, it
will try to find a cast or promotion operation to resolve the mismatch. If it finds one
non-ambiguous way to resolve the types, it applies that way, otherwise compilation fails.
This design is fairly large and, in a few places, a bit complicated. However, the result is that
we can use instances of Str to represent strings, just as if they were of a type defined
by the C++ language. We can copy them, assign them, index them, ..., without participating in
the instance's resource management.
The result is that the designer had to spend a lot of time getting all the details defined
correctly, but users simply using the class without having any knowledge about its design
other than its class interface.
bottomSTR MethodsSTR classtop