Re: teaching examples for inheritance and polymorphism
On 03/12/2013, Stefan Ram wrote:
> I was asked to teach ?inheritance? and ?polymorphism? in C++.
>
> Usually, I would not approach teaching this way, but instead
> teach ?C++ class design? and then show what's appropriate,
> possibly teaching delegation before inheritance. But now the
> time is limited, so I cannot teach everything from ground up
> in my way, and I still want to answer those questions as asked.
>
> My problem is finding good teaching examples and exercises.
> Somehow, I hate teaching inheritance by ?a cow is an animal?
> or ?a rectangle is a square?, or polymorphism by
> ?cow.makeSound()? versus ?cat.makeSound()?, because those
> examples seem so artificially constructed for teaching but
> rarely arise in real-world C++ applications.
Yeah, I hate those examples, too. I often fail to grasp the idea behind
those examples (if there is one), and even if I do, I often lack the
enthusiasm to get it to work (it's like working for the waste-bin).
> Is anyone aware of examples where inheritance or
> polymorphism really shines in C++, that are taken from
> real-life applications of C++ or are something that can be
> obviously useful in C++ programming, but are also rather
> small and do not require too much knowledge of C++ (i.e.
> only require knowledge of classes and derivation of classes
> but not of, say, generics)? Some simple examples where
> inheritance or polymorphism really makes sense?
What about this: Create a program that let's the user enter a function
R->R in the source code. The user should be able to compute the function
at various places and compute the derivation of the function. The set of
function that should be supported should enclose polynomials, sine and
cosine. New functions must be creatable from existing functions through
sums, products and composition. The following code should compile and
yield proper values:
int main ()
{
// TODO: Choose useful function!
Function f = Sine (Const (3) * Id * Id); // = sin(3x^2)
std::cout << f->Derive () (0.3) << std::endl;
// = 6x * cos(3x^2) = 1,73479
return 0;
}
This task introduces both polymorphism and operator overloading in a
nice manner. The problem domain should be easily comprehensible for high
school students. Once an interface for Function is agreed upon,
individual groups can implement different functions, so the task may be
possible to do in 90 minutes (I haven't tried this in a real class, so
it may be the case that this takes much longer).
It will take a while until students will realize that there needs to be
not only the primitive Function classes like Sine, Cosine, and Id, but
also some kind of meta-function classes for Products, Sums, and
Composition. Once this has been accomplished, they will probably use the
following interface for Function objects:
class FunctionInterface
{
public:
virtual double operator () (double x) const = 0;
virtual FunctionInterface* Derive () const = 0;
};
For simplicity's sake they should ignore any problems with leaking
memory. Once they got that to work, they will realize the syntax of main
function of the task cannot be achieved with pointers alone, at least
not operator () (Function* innerFunction), so they will have to use some
wrapping class. I used a class that simply derives from
std::shared_ptr<FunctionInterface> and adds operator ().
Maybe this is a bit too complicated for a single session, but the task
could be split into one session that implements the object-oriented
part, and one session that deals with memory management, and one session
that adds the operator overloading part. In this case you would have to
change the task a bit and make it more and more complicated.
A real nice feature would be, if you provided some sort of visualisation
that can be used to plot their functions. However, I would not let this
be done by the students, since this draws their attention too much away
from the concepts of C++ to the concepts of some GUI library.
Regards,
Stuart