A
Alf P. Steinbach
I'm relatively new to C++ programming and have a few questions:
Having worked with QT for some time, I like instantiating my objects with the new operator and
juggling with pointers to them rather than using the objects directly.
As my programs become more and more complex I am at a point where it might be wise to ask the
experts about some issues. Please look at the two following examples:
I have a main class DProjectionDataSet and a derived class PDSet inherited from DProjectionDataSet.
Let the Copy() function be a member of DProjectionDataSet:
DProjectionDataSet *DProjectionDataSet::Copy ()
{
DProjectionDataSet *new_data_set = new DProjectionDataSet ();
...
<copy 'this' to 'new_data_set'>
...
return new_data_set;
}
The following then works in main:
PDSet *dataset = new PDSet (input_file, MEM);
PDSet *slice = (PDSet*)dataset->Copy ();
, but I have to have the cast in the second line (lest I get: error: invalid conversion from
`DProjectionDataSet*' to `PDSet*'). I thought that due to the inheritance dataset->Copy() would
return a PDSet, but according to my Linux g++ compiler it returns a DProjectionDataSet, which I have
to cast to a PDSet.
The dynamic (runtime) type is PDSet*, the static (compile-time) type is
DProcejectionDataSet*.
But that's only because you haven't used C++'s allowance for covariant
return types.
With a conforming compiler you can declare PDSet::Copy as
PDSet* Copy() const { ... }
and it will still override DProjectionDataSet::Copy.
I have also defined an operator+:
DProjectionDataSet *DProjectionDataSet:perator+ (DProjectionDataSet *data_set)
{
DProjectionDataSet *sum = this->Copy ();
...
<add the contents of 'data_set' to 'sum'>
...
return sum;
}
Unconventional return type.
To make operator+ work as expected it should return "DProjectDataSet const&".
For efficiency you might consider also providing operator+=.
1.) Could it be that by the way I instantiate my classes in main (i.e. via pointers) I make it
difficult/impossible for the compiler to recognize how the objects are derived from each other and
how the data types correspond?
No, the difficulties stem from not using covariant return type.
2.) Is the pointer-oriented approach a bad philosophy (the QT people do it quite a lot)? I kind of
like how you can pass the pointers around. I tried rewriting the code using references, but it got
really awkward. Maybe I was doing it wrong.
Using raw pointers is not a good idea.
Consider at least using std::auto_ptr (also see e.g. boost::shared_ptr).
3.) If it is ok to stick to 2.) are there more elegant possibilities as the ones shown above, i.e.
can I get rid of the casting?
Yes, you can; see above.