Category Archives: testing

testing, casting & implicit conversion, and methods vs functions

This past week in OOP we discussed how to test private and protected members of a class in C++ without having to change the implementation, casting and implicit conversion and how to turn it off in C++, and we looked at methods vs functions.

The first discussion was motivated by the project which was due on wednesday and the fact that it is nice to be able to test internal state but many of the solutions involved making the class a friend of the tester which required some work and portrayed an object model that was not entirely true, and furthermore might need maintenance in the future. The better solution was to use compiler directives to expose all of the members and as such the state, the code for which would look something like:

#define private public
#define protected public
#define class struct

#include "darwin.h" //the header file we wanted to include in the tester

With reference to casting we covered the fact that in C++ we can typecast an int to a double, which we can also do in Java, however we can also typecast a double to an int(with a loss of precision) which we can’t do in Java. Prof Downing also introduced that fact that the one arg constructor was an implicit conversion function from the type of the argument to the type of the object, in some cases though this is undesirable so by defining the constructor with the keyword ‘explicit’ we can force this implicit conversion to not happen, we then sacrifice the nice syntax of <Type> x = <value>; and we are forced into using the otherwise equivalent <Type> x(<value>); syntax. In C++ we can additionally define functions for other types to allow conversion of the user defined type to the other type, the syntax for which is as follows:

operator <some_type_here>(){...} //will always return a value of type <some_type_here>

In cases where these implicit conversions might cause problems the compiler will prefer the non-converted function.

Progressing through the list we come to the comparison of functions vs methods and when to use which. Functions belong to no class or rather they exist in the file/global scope whereas methods are bound to a class. Methods normally my first choice coming from Java but when deciding which to use one should ponder the following questions: “does the public interface provide all the access we need to perform the function?”, “do we need to define the operation with a different class on the left hand side(example: ostreams’  << and  istreams’ >> operators)?”, and “do we want the operation to be symetric?”. If you answered yes to any or all of the above then it might be worthwhile to define the code block as a function(using friend if necessary).

Heap Emulation

This week in OOP we began focusing on type casting in C++ as well as allocation strategies and data storage strategies.

The type casting of C++ is a bit more verbose than it is in most other languages, the reason being is that often when typecasting data is truncated and latter we find that this data was needed, so since errors sometimes result C++ has taken to making typecasting easy to spot by giving it an overly verbose form. An example of this is the following:

int& view(char& c) const{
return *reinterpret_cast<int*>(&c);
}
 

The allocation and data storage strategies we reviewed were the following:

  • in C++ most systems interpret a char as 1 byte, as such it is a lightweight way to store general byte data.
  • to denote free space in a heap we can create sentinel values as int values(aka: 4 bytes), often these values might get overwritten accidentally, so to provide some minor error checking store two copies of each sentinel required.
  • to denote active/taken blocks use a negative value to distinguish between free blocks(positive values)

By using this information as well as some unit tests developed on the native heap manager we hope to achieve a similar heap manager that allows us more granular control of the data it has allocated, this is stricly for educational purposes of course.

performance and backing of data structures and c++ iterators

In the days that lead up to the test I found that most of my time was spent trying to chase down an off-by-one bug and in class brushing up on data structures and iterators. The earlier problem was resolved by spending roughly 5 hours running through the code inserting statements to help us see how the code was breaking and then exploring how to get GDB working with the eclipse CDT plugin. The latter was an exercise in note taking.

To recap the 5 common C++ iterators and the operators they provide are:

  • Input: !=, ==, *(read only), ++
  • Output: *(write only), ++
  • Forward: all of input’s and it can read or write on *
  • Bidirectional: all of forward’s and —
  • Random Access: all of bidirectional’s and [], +, -, <, >, <=, >=

As such if you want to make a method which accepts the most iterators you should only expect the operators provided by input or output and no others. However, < tends to be more robust as it will terminate in the case of the begining and the end iterator getting mixed up where inputs != won’t.

In the data structures discussed we looked at cost of selecting, removing, and adding elements which belong to various structures…. most of this discussion was review to me but the discussion continued to the different underlying data structures that could be used to build stacks, queues, and priority structures and this was something that I had not thought about. In summary the subcomponents were vectors, linked lists, and tree structures and stacks can use any of these, queues can use any but vectors, and priority queues can use any but linked lists.