IN204 - Software Engineering - Object Oriented

Transcription

IN204 - Software Engineering - Object Oriented
IN204 - Software Engineering - Object Oriented
Programming
Tutorial 6 - Generics - November 4, 2016
B. Monsuez, F. Vedrine, A. Cutean, V. Paun
Preamble
You can find a reference guide on the IN204 course web page http://wwwdfr.ensta.fr/Cours/index.php?
usebdd=ensta&sigle=IN204&afficher=biblio
The purpose of the TD is to study the technique for writing algorithms running with not one type of specific
data but several possible data types.
We consider a simple sorting algorithm which we give the natural implementation for Integers as follows:
voidtri_simple(int*lesValeurs,inttaille)
{
for(inti=0;(i<taille);i++)
{
for(intj=i+1;(j<taille);j++)
{
//Comparesilesdeuxelementssontdanslebonordre.
if(lesValeurs[i]>lesValeurs[j])
{
//Procedealapermutationdesdeuxelements
intTemp=lesValeurs[i];
lesValeurs[i]=lesValeurs[j];
lesValeurs[j]=Temp;
}
}
}
}
Part 1 - Using a base object exposing virtual methods
We want to rewrite the previous sorting algorithm tri_simple in an algorithm that rather than ordering
an integer array, now orders an array of pointers to objects of type Integer , the Integer class is a
class implementing integers.
Question 1: Defining the class Integer
The class Integer stores an integer data and is used to define an object bahaving as the primitive type
int .
We wish to add integer operations in this class. Among these operations, there are in particular
1. access operations:
The assignment of an integer value
The recovery of an integer value
2. comparison operations
3. display/print operations
Complete the skeleton class Integer .
classInteger
{
private:
intvaleur;
public:
Integer(){valeur=0;}
Integer(intuneValeur){valeur=uneValeur;}
//Affectelavaleurstockéedanslaclasse
voidset(intuneValeur)
{
...
}
//Récupèrelavaleurstockéedanslaclasse
intget()const
{
...
}
//Comparedeuxentiers.
//Silavaleurdel'objetcourantestpluspetitequelavaleurstockeedansl'objet
//passeenparametre,retourne-1
//Silavaleurdel'objetcourantestplusgrandquelavaleurstockeedansl'objet
//passeenparametre,retourne+1
//Silesdeuxvaleurssontegales,retourne0
intcompare(constInteger&unEntier)
{
...
}
//Imprimelavaleursurlefluxstd::iostream<char>
voidprint(std::ostream<char>&leFlux)
{
...
}
...
};
Question 2:
Definition of an array of pointers on classes Integer
We wish to have a function that creates an array of n elements of type Integer . In this table
elements are not stored, but the pointers to the type of elements Integer . Since the table was allocated
dynamically, it is imperative to proceed with the destruction of the elements of this table during the
destruction of the table.
We provide two functions, a first createArrayOfInteger function that creates such a table and a
second freeArrayOfInteger function that destroys such a table.
Integer**createArrayOfInteger(intn)
{
Integer**result=newInteger*[n];
for(inti=0;i<n;i++)
result[i]=newInteger();
returnresult;
}
voidfreeArrayOfInteger(Integer**leTableau,intn);
{
for(inti=0;i<n;i++)
deleteleTableau[i];
delete[]leTableau;
}
We would assign random values ​between 0 and m in an array of integers. Write the function
voidrandomArrayOfInteger(intm,Integer**leTableau,intn);
{
...
}
which affects such a full table of random values ​between 0 and m. To do this, we suggest using the
following random function to draw a pseudorandom number between 0 and m.
intrandom(intm)
{
return(rand*m)%RAND_MAX;
}
Then write a function that displays all the elements in the array.
voidprintArrayOfInteger(std::basic_ostream<char>&leFlux,Integer**leTableau,intn);
{
...
}
Test these functions.
Question 3:
Change tri_simple in the tri_simple_entier function so that it now sorts an array of integers
of type Integer ** .
Test the modified function behaves correctly.
Question 4:
We now want to modify the tri_simple_entier function such that it will be able to not only sort
integers but objects of type Object.
Question 4.1:
Identify methods that the function tri_simple_entier needs so that it can sort objects of type
Integer .
We propose to write an abstract virtual class that exposes the definition methods that the
tri_simple_entier function needs to sort the objects.
Write this Object class.
Question 4.2:
Change the code in tri_simple_entier into tri_simple_object such that it can take into
account no longer arrays of Integer ** but arrays of Object ** .
Question 4.3:
Change the Integer class in a class that derives from an Object class and overloads the virtual
methods exposed by Object .
Test now the tri_simple_object function.
Question 5:
We provide a class String which implements strings and objects derived from Object . We provide
same functions
String**createArrayOfString(intn);
voidfreeArrayOfString(String**leTableau,intn);
voidrandomArrayOfString(intm,Integer**leTableau,intn);
voidprintArrayOfString(std::ostreamleFlux,Integer**leTableau,intn);
implementing the functions identical to those defined on integer arrays.
Is it possible to use the tri_simple_object function to sort an array of integers? Verify your
statement?
Question 6 (complementery work - not included in this Tutorial)
We now consider the quick sorting algorithm Quicksort known in the literature. Here we give a version
running on integer arrays.
Transforming functions so that they can accommodate different sized boards Object .
Verify the correct behavior of the algorithm on integers and strings.
Part 2 - Using templates or "template" for functions
In the previous approach, all objects are inherited from a common type that exposes the methods required
by the algorithm that is to be implanted. This approach can effectively implement a form of generics.
However it has two drawbacks including:
It requires systematic use of virtual methods, which has a cost in terms of typing.
It only allows to ensure that the compilation manipulated elements are of a type that inherits from a
base type but not the type that is actually expected.
Assuming that the code works as the identity function works for many types:
int identite(int x) {return x ; }
and it is also possible to write a function:
double identite(double x) {return x ; }
and so on ... it became interesting to define a syntax for not having to recopy the code of the function when
we need to define a type for x, y or z!
Accordingly, it is possible to write:
template<class T> T identite(T x) { return x ; }
which means that the "identity" function is defined for a parameter x. During a call to the function with a
parameter x identity with T1-type, the compiler will automatically generate the code:
T1 identite(T1 x) { return x ; }
And it will compile this code.
Question 1
We consider tri_simple function defined in the header of the subject. We want to make this generic
code to work on both arrays of integers but also on other types of tables elements. Turn this feature
tri_simple in tri_generique in order to make these changes.
Question 2
We provide createRandomArray() function creates an array of integers, floating numbers and details
of strings. Check that your tri_generique function works for each table.
Part 3 - Using templates or "template" for classes
We have defined a class Integer storing integer values. To carry on, it would be necessary to set a
Double class to store values. In the same way as for functions, it is possible to define a template class.
template<classT1,classT2>
classPaire
{
private:
T1x;
T2y;
public:
Paire():x(),y(){}
Paire(T1a,T2b){x=a;y=b)
};
If we want a pair of integers, we will write:
Paire<int, int> maPaire ;
Which will automatically generate from the previous model the following class:
classPaire<int,int>
{
private:
intx;
inty;
public:
Paire():x(),y(){}
Paire(inta,intb){x=a;y=b)
};
Question 1
Propose a template<class T> Value class deriving from Object such hat Value <int> will
be strictly equivalent to the Integer class.
Check that it is possible to define the class Double as Value <Double> .