|
-
January 21st, 2003, 10:22 PM
#1
Hiding new/delete
Object creation/destruction.
I wonder if any of you c++ guru's could give me insight into a philosophical design issue. Forgive me if the answer is simple, I have an assembly background.
Consider the following...
class session
{
virtual void ProcessData() = 0;
};
class mysession : public session
{
public:
virtual void ProcessData() {}
};
class sessionlist
{
public:
session* NewSession()
{
return AddToList( new mysession() );
}
void RemoveSession( mysession *s )
{
RemoveFromList( s );
delete s;
}
session* AddToList( session* s ) { return s; }
void RemoveFromList( session* s ){}
};
class server
{
public:
sessionlist sl;
void OnAccept()
{
Accept( sl.NewSession() );
}
void OnDissconnect( session *s )
{
}
void Accept( session* s ) {}
};
It would be nice if I could add server, serverlist, and session to a library. All I would have to do is derive a class from session for my specific implementation then use server and serverlist as is. However, because new and delete must know the object type to properly create and destroy the object. In this case I must also use a special instance of session list. Just to call the correct version of new and delete! This type of thing comes up all the time for me. I can hide everything away except the creation and destruction of objects. What I actually do to get around it is define a function type such as...
typedef session* (*session_CreateSession)();
typedef session* (*session_DeleteSession)( void* ptr );
... then create static functions in 'mysession' and call a 'SetCreateDestroyFunctions()' inside of sessionlist. But I don't consider this to be very elegant.
So the question is, is there a nice elegant 'c++' way to handle this situation?
Thanks for any response.
- Robert
-
January 21st, 2003, 10:43 PM
#2
1) You really Dont want to.
2) You should extract the declaration from the definition (fancy words for use .h (or .hpp) and a .cpp file (typically each class can be in their own.
Now to USE your classes, SOME function provided by them, i not then post again.
You can totally minimize what they can create/destroy by hiding the constructor and destructor (easier and more "standard" than hiding new/delete). Then provice a static member function or flobal function (I prefer the former. Since nothing can be created or deleted outside your DLL, you can solve some sneaky memory conflicts (new from one freestore delete to a different one)
Hope this helps.
TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
2008, 2009,2010
In theory, there is no difference between theory and practice; in practice there is.
* Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions 
* How NOT to post a question here
* Of course you read this carefully before you posted
* Need homework help? Read this first
-
January 21st, 2003, 11:14 PM
#3
< 2) You should extract the declaration from the definition (fancy words for use .h (or .hpp) and a .cpp file (typically each class can be in their own. >
I would normally, just trying to create an example for the board.
Perhaps you could expand on your statement <You really Dont want to>. I really just want to derive one class instead of two.
My current fix would be to add functions such as
Code:
typedef session* (*session_Create)();
typedef void (*session_Delete)( session *ptr );
class mysession
{
static session* sCreate();
static void sDelete( session *ptr );
};
session* mysession::sCreate() { return new mysession; }
void mysession::sDelete( session *ptr ) { delete (mysession*)delete; }
class sessionlist
{
session_Create m_fCreate;
session_Delete m_fDelete;
void SetSession( session_Create c, session_Delete d )
{ m_fCreate = c; m_fDelete = d; }
};
// Somewhere in code
sessionlist sl;
sl.SetSession( mysession::sCreate, mysession::sDelete );
This gets me what I want, sessionlist now does not have to know anything about the mysession class and can be safely tucked away in a library somewhere. This solution never seemed very elegant to me. I've been coding for 15 years and this is the best I've ever come up with. I just thought as I was coding here late at night, that someone out there might have a better way of handling this situation.
-
January 21st, 2003, 11:53 PM
#4
Been coding over 30. Again, you REALLY dont want to
See Scott Meyers Effective C++ for a good explaination, it is available on-line, but I dont have the url handy.
It does not need to know about mySession only Session. Just don't have the list do the construction (that is often not a good it since it limits you).
Also curious about why you seem to be inventing the Wheel? Why not STL container for SessionList?
TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
2008, 2009,2010
In theory, there is no difference between theory and practice; in practice there is.
* Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions 
* How NOT to post a question here
* Of course you read this carefully before you posted
* Need homework help? Read this first
-
January 21st, 2003, 11:59 PM
#5
If the only thing you want is the ability to change what ProcessData does, why not use the Executor Design Pattern, or a CallBack OBJECT rather than a virtual function?
Now you can put EVERY thing tightly in a DLL and just pass in the Executor or the Callback object....
TheCPUWizard is a registered trademark, all rights reserved. (If this post was helpful, please RATE it!)
2008, 2009,2010
In theory, there is no difference between theory and practice; in practice there is.
* Join the fight, refuse to respond to posts that contain code outside of [code] ... [/code] tags. See here for instructions 
* How NOT to post a question here
* Of course you read this carefully before you posted
* Need homework help? Read this first
-
January 22nd, 2003, 12:31 AM
#6
There is nothing special about the code I posted, although it is simliar to something I'm coding right now.
I guess my issue is, in the situation where a superclass is used to define an interface, this gives you access to the specialized functionality of subclasses which you are not yet aware of, but it seems there is no way to create and destroy subclasses classes without specifically coding for it. It would be nice if you could somehow pass a subclass type as a parameter.
I was expecting someone to tell me 'That's what OLE/COM is for'. I realise that, but that is a lot of overkill for a few simple classes.
Just thought there might have been a common way of getting around this. Maybe as you seem to indicate, it is just poor design on my part for running into these situations in the first place. Sadly, I'm stuck with my skills as they are.
Thanks for your time. Just thinking about it at least helps me pin-down the problem. I'll try and rethink my approach in general.
By the way, no luck finding 'Executor Design Pattern' on Google, however, callback objects I do understand and may be the way to go. Thanks again.
-
January 22nd, 2003, 04:35 AM
#7
I'm not sure if I understand your problem, but it looks like what you really are after is a way to create / destroy derived classes that a client may build, so that you can work with derived objects you know nothing about (except for interface -- because they have not yet been built!). If this is true, then you seem to have found the solution already, but in a strangely c code manner. The common pattern is to use a "Factory Method", or basically a virtual Create (delete just needs the instance, not the type, so the mirror "Junkyard Method" is needed only with additional reasons, like tracking). You have a virtual Create in the c sense of polymorphism, with its lesser type safety.
But I can't be too sure if that is what you want. Your style can be transformed with a little more structure into a Command Pattern, and there has already been some talk of callbacks and functors in this thread. But that seems like it may be decoupling the pieces too far, since the derivation is not being used to its advantage. Of course, if you wanted to make the library objects to be contained instead of to be derived from, then functors will soon become your friend.
The mentioning of a library also confused me, as I wasn't sure if the question was more relevant to implementation hiding than I have yet responded to. Talking about "hiding new and delete" could be interpreted as was discussed earlier in terms of access (public / private) or in terms of hiding the code into an object file (or dll), and so its hard to pinpoint a solution without a little more clarification.
*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/
"It's hard to believe in something you don't understand." -- the sidhi X-files episode
galathaea: prankster, fablist, magician, liar
-
January 22nd, 2003, 05:42 AM
#8
Originally posted by rpmivh
There is nothing special about the code I posted, although it is simliar to something I'm coding right now.
I guess my issue is, in the situation where a superclass is used to define an interface, this gives you access to the specialized functionality of subclasses which you are not yet aware of, but it seems there is no way to create and destroy subclasses classes without specifically coding for it. It would be nice if you could somehow pass a subclass type as a parameter.
Does this help?
http://www.parashift.com/c++-faq-lit....html#faq-20.6
This is the usual way to create derived objects from the base object, and the base object doesn't have to know anything about the derived objects.
Also (as CPU Wizard points out) you are reinventing the wheel by creating a "sessionlist" class. You could easily have a std::vector<Session*> instead of creating a class.
Regards,
Paul McKenzie
-
January 22nd, 2003, 10:01 AM
#9
Thanks Paul,
The FAQ helps alot. At least using a virtual destructor gets me out of having to specifically destroy the object. And all this time I've been avoiding calling delete on base types. I suppose I should read the boards more often. 
From what I understand from the FAQ, this would then be the 'usual-way' of handling the situation. If I understand, aloof() should create and destroy mysession correctly despite not knowing the type in advance. The only disadvantage I see to this is the creation of the temporary object. Now if C++ only had virtual static functions...
Code:
class session
{
public:
virtual ~session();
virtual void ProcessData() = 0;
virtual session* clone() { return NULL; }
static session* create( session* ptr ) { return ptr->clone(); }
};
class mysession : public session
{
public:
virtual void ProcessData() {}
virtual session* clone() { return new mysession(); }
};
void aloof( session *tmpl )
{
session *ptr = session::create( tmpl );
// ...
delete ptr;
}
void f()
{
aloof( &mysession() );
}
By the way, I'm not ignoring comments about using stl, this was just an example, my real issue was the creation/destruction of derived classes using only the base pointer. I just wasn't sure how to ask the question earlier.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|