Dynamic allocation and destruction

F

Fred Mangusta

Hi,

I have an object, Model, that creates another object, Trainer.
Trainer, given some data, fills some structures with processed data.

My problem is the following: I need to pass those structures back UP to
Model, because I want to use Model's save method to save them into a
file. I could save them through Trainer directly, but I would like to
concentrate all file operation in Model, and not scatter them all around.

I'm not really sure about the correct way to achieve this.

I managed to write some code that does this, but I have concerns about
the lifetime of the objects in question. This is my way of doing this:

I created the following public method in the Trainer class:

bool Trainer::setDataSTRUCT(RandLMStruct* &struct_,
RandLMInfo* &info_,
LogQuantiser* &quantiser_){

assert(TrainerStruct != NULL);
struct_ = TrainerStruct;
assert(TrainerInfo != NULL);
info_ = TrainerInfo;
assert(TrainerQuantiser != NULL);
quantiser_ = TrainerQuantiser;
return true;
}

where
randlm::RandLMStruct* TrainerStruct;
randlm::LogQuantiser* TrainerQuantiser;
randlm::RandLMInfo* TrainerInfo;

are pointers to the objects, allocated, owned, and filled with data by
Trainer: I want to use setDataSTRUCT to pass these UP to Model.

struct_, info_ and quantiser_ instead, are in the definition of the
Model class.

Therefore in model.h, I have what follows:

class Model {
public:
Model(): info_(NULL), struct_(NULL), quantiser_(NULL){}

//public methods...

private:
//these will get data from Trainer.

randlm::RandLMInfo* info_;
randlm::RandLMStruct* struct_;
randlm::LogQuantiser* quantiser_;
};


Soon after Trainer has been called by Method to process the data,

//..
scoped_ptr<Trainer> t;
t->train(...)
//...

I would like to call it passing struct_, info_, quantiser_ by reference,
as follows:

t->setDataSTRUCT(struct_,info_,quantiser_);


Now, is this approach correct? I'm not sure regarding WHO destructs the
three objects after I will have their contents saved in the file. In
fact, if I create a destructor in Model(), and write something like

~Model() {
delete info_;
delete struct_;
delete quantiser_;
}

gcc complains: this is understandable, because I have not allocated
space for them, but just made them point to already existing objects
(TrainerStruct, TrainerInfo, TrainerQuantiser).

But then if Trainer destroys these pointers, will the data to which they
point to be still available when I will need to write it - this time
using info_, struct_, quantiser_??

Is all of the above correct? Do you suggest some better approach?

Thank you in advance for your clarifications.

F.
 
P

Puppet_Sock

I have an object, Model, that creates another object, Trainer.
Trainer, given some data, fills some structures with processed data.

My problem is the following: I need to pass those structures back UP to
Model, because I want to use Model's save method to save them into a
file. I could save them through Trainer directly, but I would like to
concentrate all file operation in Model, and not scatter them all around.
[snip]

I detect a FORTRAN coder. This is a thing that a lot of
old FORTRAN coders want to do, have a module that does
all the I/O. The notion seems to be information hiding.
They think they are winning because they have hidden all
the I/O in a module, and so expect all the changes due
to changes in the input or output files will be hidden.

Then they pass all the data around in a monster COMMON
block (I've seen COMMON blocks with 500 variables in them)
and wonder why their code breaks so often.

Don't try to concentrate your I/O in one class.

In your case, you want to implment an output function,
or possibly a << operator, for each class. The class
Model has to know it has a Trainer object. So when the
application decides it is time to start outputting to
a file, the Model starts outputting each of its member
objects.

System tells Model to write itelf
Model tells each data member to write itself
each data member, including Trainer, writes itelf.

It's delegation. So Model does not know what is
doing on inside Trainer in any more detail than
is required.
Socks
 
F

Fred Mangusta

Puppet_Sock said:
I detect a FORTRAN coder. This is a thing that a lot of
old FORTRAN coders want to do, have a module that does
all the I/O. The notion seems to be information hiding.
They think they are winning because they have hidden all
the I/O in a module, and so expect all the changes due
to changes in the input or output files will be hidden.

Then they pass all the data around in a monster COMMON
block (I've seen COMMON blocks with 500 variables in them)
and wonder why their code breaks so often.

Hehe no, I wish a was a Fortran coder, but to be honest I cannot even
call myself a coder :) I'm relatively new to OOP and I just thought it
was good programming practice to have all data I/O managed by the
"upper" class, (for better control maybe?) and information hiding.

Don't try to concentrate your I/O in one class.
ok

In your case, you want to implment an output function,
or possibly a << operator, for each class. The class
Model has to know it has a Trainer object. So when the
application decides it is time to start outputting to
a file, the Model starts outputting each of its member
objects.

System tells Model to write itelf
Model tells each data member to write itself
each data member, including Trainer, writes itelf.

So what you're saying is something like:

system.save(){
model.save()
}

and then

model.save(){
save(owned data);
trainer1.save();
trainer2.save();
....
}

Is that right?
It's delegation. So Model does not know what is
doing on inside Trainer in any more detail than
is required.
Socks

Thanks!

F.
 
E

Erik Wikström

Hehe no, I wish a was a Fortran coder, but to be honest I cannot even
call myself a coder :) I'm relatively new to OOP and I just thought it
was good programming practice to have all data I/O managed by the
"upper" class, (for better control maybe?) and information hiding.

No, one important part of OO is the concept of data hiding, you want to
hide how the various classes are implemented and only allow manipulation
via member functions. This also makes changes to the code more local,
when you change the Trainer class you also make the changes to the code
that writes the data to file in the Trainer class.

This has the advantage that if you someday make a Model2 class that also
have some Trainer members (but is otherwise different from Model) you do
not have to make changes to both Model and Model2 when you make changes
to Trainer (as long as you do not change how its member functions works).
So what you're saying is something like:

system.save(){
model.save()
}

and then

model.save(){
save(owned data);
trainer1.save();
trainer2.save();
...
}

Is that right?

Yes.
 
D

Daniel T.

On 2008-07-27 10:49, Fred Mangusta wrote:



Yes.

I can't agree. What happens when you find that you have to save in
some format that isn't a flat file? If you have to change every class
in the program, then the above is a bad idea.

It *is* best to seperate "what needs to be saved" from "how to save
something."
 
P

Puppet_Sock

I can't agree. What happens when you find that you have to save in
some format that isn't a flat file? If you have to change every class
in the program, then the above is a bad idea.

It *is* best to seperate "what needs to be saved" from "how to save
something."

Somebody needs to know both how to save the data, and
what data there is to save. If a class has data that
it does not expose, but you don't want a member function
to do the write-to-file operations, how do you want to
do it?
Socks
 
I

Ian Collins

Daniel said:
I can't agree. What happens when you find that you have to save in
some format that isn't a flat file? If you have to change every class
in the program, then the above is a bad idea.

It *is* best to seperate "what needs to be saved" from "how to save
something."

Indeed it is, but not in the way you suggest.

Use an abstraction for the "file":

model.save( File& file ){
save(owned data, file );
trainer1.save( file );
trainer2.save( file );
}

Or if like me, you like streams:

model.save( File& file ){
file << ownData << trainer1 << trainer2;
}

Objects know how to stream them selves to/from a File, File knows how to
write the data to the underlying persistence later.
 
J

James Kanze

Daniel T. wrote:

[...]
Objects know how to stream them selves to/from a File, File
knows how to write the data to the underlying persistence
later.

So Objects know BER format? And they know XDR? And every other
format ever invented?

Persistency is one of the more difficult things to do cleanly,
because you don't want the object to have to know the details of
the format (with the possible exception of some sort of text
format), and you don't want the formatter to know anything about
the object.

In this case, iostream got it right. It cleanly separates the
formatting (istream/ostream) from the reading and writing
(streambuf), and it puts the individual formatting in separate
functions, independent of both the stream and the object. (The
person writing that function, of course, generally needs to have
some knowledge of both in order to do so. But the class itself
isn't burdened with knowledge of the format, and the basic
stream objects are independent of the classes that are to be
formatted.)
 
I

Ian Collins

James said:
Daniel T. wrote:
[...]
Objects know how to stream them selves to/from a File, File
knows how to write the data to the underlying persistence
later.

So Objects know BER format? And they know XDR? And every other
format ever invented?
No. BER_File or XFD_File will know in the same way as an fstream or s
stringstream knows what to do with streamed data.
Persistency is one of the more difficult things to do cleanly,
because you don't want the object to have to know the details of
the format (with the possible exception of some sort of text
format), and you don't want the formatter to know anything about
the object.
Which, I think, is exactly what I said above.
In this case, iostream got it right. It cleanly separates the
formatting (istream/ostream) from the reading and writing
(streambuf), and it puts the individual formatting in separate
functions, independent of both the stream and the object.

I frequent use a binary stream object which works in the same way.
 

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

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,241
Members
46,833
Latest member
BettyeMacf

Latest Threads

Top