Semi-newbie question concerning programming style

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::eek: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.
 
R

Rolf Magnus

Alf said:
Using raw pointers is not a good idea.

Consider at least using std::auto_ptr (also see e.g.
boost::shared_ptr).

Well, that wouldn't be such a good idea. Qt uses its own mechanism to
delete the objects. There are two types of objects. One uses a simple
value-based approach that most often internally uses COW (like strings
and pixmaps e.g.), the other type is derived from QObject, and each
object of that type has a parent object (think of all the buttons and
stuff in a dialog having that dialog as parent e.g.), and when the
parent is destroyed, all the children are automatically destroyed too.
Shared pointers don't really fit in there, and aren't actually needed.
Yes, you can; see above.

Btw: never use C style casts. Instead use the new C++ casts, _if_ you
need to cast at all.
 
A

Alf P. Steinbach

Well, that wouldn't be such a good idea. Qt uses its own mechanism to
delete the objects. There are two types of objects. One uses a simple
value-based approach that most often internally uses COW (like strings
and pixmaps e.g.), the other type is derived from QObject, and each
object of that type has a parent object (think of all the buttons and
stuff in a dialog having that dialog as parent e.g.), and when the
parent is destroyed, all the children are automatically destroyed too.
Shared pointers don't really fit in there, and aren't actually needed.

I agree that it it's a bad idea to impose more than one ownership regime.

If you can never create an object that isn't owned by another object, then
a boost::shared_ptr (say) would be an additional ownership, which could
have disastrous results. But perhaps Qt offers some smart-pointer
classes itself, smart-pointer classes that cooperate with the hierarchical
ownership?

On the other hand, if free-standing objects can be created, then any
smart-pointer would probably be an improvement over raw pointers, for this
case.



Btw: never use C style casts. Instead use the new C++ casts, _if_ you
need to cast at all.

Yup. I forgot to mention that.
 
P

Peter Forthmann

Hi,

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.



I have also defined an operator+:



DProjectionDataSet *DProjectionDataSet::eek:perator+ (DProjectionDataSet *data_set)
{
DProjectionDataSet *sum = this->Copy ();
...
<add the contents of 'data_set' to 'sum'>
...
return sum;
}



Also then the add operation works ok in main, but it's even worse than in the previous example,
because I need to dereference the first operator also:

PDSet *sum = (PDSet*)(*slice + slice);




My questions now are the following:

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?

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.

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?


Thanks a lot for your help guys,

Peter.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top