Bits & Bytes

Posts Tagged ‘program’

UML Class Diagrams – part 2

Continued . . .

Previously, we demonstrated a basic class diagram of a simple class that could be used for creating points in the plane. Now we will expand on the elements of what we showed before with some additional details in our UML class diagram. To be sure, we will still have more details to add when we are done here, but rest assured we will fill out everything in the end.

We begin with the C++ header code below for a polygon class, called CPolygon; this class could be used in conjunction with our previous point class to represent polygons in the plane. This polygon class consists of two member variables: an int to hold a count of the number of vertices in the polygon and a pointer to a dynamically allocated array of vertices that are CPoint objects. Additionally, there are four simple member functions to calculate the centroid (center point), add a vertex, set a vertex, and get a vertex. For simplicity, we have ignored constructors and the destructor.

class CPolygon
{
public:
    CPoint Centroid();
    void AddVertex(CPoint qP);
    void SetVertex(int i, CPoint qP);
    void GetVertex(int i, CPoint& qrP);

private:
    int miVertexCount;
    CPoint* mqpVertices;
};

A UML diagram for this class is shown below. Notice that this diagram includes some details that we did not show previously. We have added the member variable types, which we tacked on with a colon after the variable names. Also, directly after the variable name mqpVertices, we have added [3..*] to represent the multiplicity of the vertices in our polygon (a polygon has three or more vertices). Presumbaly, the vertices array would be reallocated and copied when AddVertex() is called to add a vertex or something like that, but we have not specified the exact behavior here.

For our operations, we add the return type after a colon. This is evident with the Centroid() function, since it has a return type of CPoint. The remaining functions have a void return type, so they return nothing. We could have shown a void return type, but we would probably never bother in actual practice. Likewise, we have omitted the void argument type for the Centroid() function. Unlike the return type, we can omit this, as we did, in the C++ code as well.

For the last three operations, we have member functions that take arguments. Since the AddVertex() function takes only one argument, we will start with it. Like our member variables, arguments have a name, then a colon, and finally the type of the argument. However, in AddVertex(), this is all preceded by the word “in” that is used to indicate that this is an input argument.

In this context, input means that the value that is passed in is important. In the GetVertex() function, the second argument is preceded by the word “out” to indicate that it is and output argument. In this case, the value that is passed in is not important, but the value that the argument variable has after the call is important. If both the input and output values are important, than we use “inout” to signify this. Lastly, notice that we replaced the commas that separated functional arguments in the C++ code with semicolons.

To be continued . . .

Operator Overloading in C++ – part 2

Continued . . .

Operator overloading offers advantages not only over C, but also over newer object-oriented languages as well. In these languages, we face the same problem. How do we make a sort that works on fundamental types and programmer-defined types? With an object-oriented structure, we can create an interface with a comparison function that all sortable types inherit. Then we can wrap native types, like double, with a class that inherits our interface, say Double. The technique of wrapping fundamental types in objects is often refered to as boxing. Converting from the wrapped type back to the fundamental type is called unboxing.

Boxing

double dTwo = 2.0;
Double qWrappedTwo = new Double(dTwo);

Unboxing

double dTwo = qWrappedTwo.GetValue();

With this technique, a single sort can work on all of our types. However, our data types suffer the memory inefficiency of the wrapping object and speed inefficiency of conversion from boxing and unboxing. Additionally, the conversions back and forth between fundamental and wrapped types is cumbersome. So, we see that templates and operator overloading offer advantages over other languages, particular in terms of speed and memory usage.

For programmers who work with numerical algorithms, operator overloading offers still more benefits. We can overload arithmetical operators to make object conform to the mathematical structures from abstract algebra like fields, rings, etc. For example, if we create a class for complex numbers or matrices, we might want to overload “+”, “*”, etc. It is important to use these operators properly. In this context, operator overloading can be very powerful.

One of the most common uses, and abuses, of operator overloading is the use of “+” to concatenate strings. Unfortunately, this usage is common in many languages and has even been used in the C++ STL string class. The STL has an elegant architecture to it, but this usage only seems to add confusion and further the idea of operator overloading as “syntactic sugar.” My problem with using “+” in string classes is that the usage does not conform to the intended mathematical meaning of the symbol.

Overloading a mathematical operator, like “+”, has many legitimate purposes in programming classes like quaternions, Taylor series, matrices, finite fields, complex numbers, vectors, polynomials, etc. If you are not working with mathematical types, overloading mathematical operators is probably a mistake.

 

© 2007–2026 XoaX.net LLC. All rights reserved.