Thread: How to access derieved class member from base class pointer

  1. #16
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by matsp View Post
    Yes, they CAN be - but as you say, it can get tricky - and it's often easier to solve that problem with a two-stage constructor, so that if you have an exception, you KNOW what has been done and what hasn't - e.g. have you filled in the "char *" value, or is it not filled in. If you do "new B" and B's constructor sets the "char *" member variable ptr = 0, then you know that part isn't going to cause an exception, but
    Code:
     
    ptr = new char[strlen(s)+1]
    could throw an exception. Now, since ptr hasn't been set to anything sensible [assuming we didn't assign it twice], so we don't know if we should delete ptr or not.

    --
    Mats
    It's true that it can get tricky, but I'd be inclined to write a tricky implementation, instead of inconveniencing the client of the class.

    I don't understand exactly what you example is, but I'm sure it could be resolved by some combination of nothrow new, a try catch function body, and separating out each discrete step into it's own try catch combo. If you explain it better, I'm sure I could provide a solution.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  2. #17
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by brewbuck View Post
    Simple rule -- don't catch exceptions in your constructors. Let them propagate out. If doing this would lead to a resource leak, it means you are not acquiring resources properly.
    I agree with most of what you said, but not with this rule. Certainly, sub objects should clean themselves up in their own destructors as much as possible. But catch and rethrow is a perfectly valid approach for when the former is impossible or suboptimal. Also, a constructor may receive ownership of an object. In such a case, it is the constructor's responsibility to clean up the object if an exception is thrown. There is no way around it.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  3. #18
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by King Mir View Post
    I agree with most of what you said, but not with this rule. Certainly, sub objects should clean themselves up in their own destructors as much as possible. But catch and rethrow is a perfectly valid approach for when the former is impossible or suboptimal.
    I can't imagine this "impossible or suboptimal" case. Do you have an example?

    Also, a constructor may receive ownership of an object. In such a case, it is the constructor's responsibility to clean up the object if an exception is thrown. There is no way around it.
    If an object is owned, it should be referenced through a smart pointer which manages ownership.

    EDIT: Also, I question whether ownership should actually be transferred if a constructor fails. Maybe the caller would like a chance to do something, instead of having the object thrown away by what looked like a simple constructor call.
    Last edited by brewbuck; 10-29-2007 at 02:03 PM.

  4. #19
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by brewbuck View Post
    I can't imagine this "impossible or suboptimal" case. Do you have an example?
    Any bottom teer object, such as a file handler, a network handler, or a memory manager.

    Really any constructor that does anything besides assign values in its body.

    If an object is owned, it should be referenced through a smart pointer which manages ownership.
    That would require the class and the client code to share the same smart pointer implementation. Also that would not work for implementing the smart pointer itself.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  5. #20
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by brewbuck View Post
    EDIT: Also, I question whether ownership should actually be transferred if a constructor fails. Maybe the caller would like a chance to do something, instead of having the object thrown away by what looked like a simple constructor call.
    At that point it's too late. If the ownership was passed from a smart pointer that smart pointer would have already released ownership when the constructor receives the argument. If it is from a call to new, that pointer is not stored anywhere except as a function argument. The options are to either free the memory, or to pass the pointer in the exception. Freeing the memory usually makes more sense.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  6. #21
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by King Mir View Post
    Any bottom teer object, such as a file handler, a network handler, or a memory manager.
    Can you give a more specific example? I can't imagine any kind of clean-up from a failed constructor that can't be handled with some simple containers.

    That would require the class and the client code to share the same smart pointer implementation. Also that would not work for implementing the smart pointer itself.
    Obviously the very, very bottom of the stack is going to have to deal with exceptions. Exception safety COMES from somewhere, yes.

    As far as smart pointers... In the case we're talking about, an auto_ptr is all that is required. It's part of the standard library. Even if it wasn't, I don't see what the problem is from an API standpoint. If the caller has to wrap up a pointer in some smart pointer class to pass it to a function, then so be it.

  7. #22
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by King Mir View Post
    At that point it's too late. If the ownership was passed from a smart pointer that smart pointer would have already released ownership when the constructor receives the argument.
    Hence the other part of what I said -- acquire resources in the right order. Transfer of ownership from one smart pointer to another is exception-free. Therefore, if this is the last thing you do in your constructor, you're fine.

  8. #23
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by brewbuck View Post
    Can you give a more specific example? I can't imagine any kind of clean-up from a failed constructor that can't be handled with some simple containers.
    Unfortunately I can't give you an example from code I have actually written.

    Containers only manage memory. If a constructor call uses other resources, like files, a network connection, or something similar, then those resources must be cleaned up. A constructor's catch block is the only place to do this.

    Case point: fstream.

    Like I said, these are generally bottom teer objects.

    As far as smart pointers... In the case we're talking about, an auto_ptr is all that is required. It's part of the standard library. Even if it wasn't, I don't see what the problem is from an API standpoint. If the caller has to wrap up a pointer in some smart pointer class to pass it to a function, then so be it.
    Quote Originally Posted by brewbuck View Post
    Hence the other part of what I said -- acquire resources in the right order. Transfer of ownership from one smart pointer to another is exception-free. Therefore, if this is the last thing you do in your constructor, you're fine.
    But what if the class doesn't use auto_ptr? What if it uses something else. It should not matter to the outside what kind of smart pointer is used internally. Therefore a raw pointer is best. But raw pointers require extra care with exception safety. So we use extra care by using catch and rethrow.
    Last edited by King Mir; 10-29-2007 at 02:43 PM.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  9. #24
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by King Mir View Post
    Containers only manage memory. If a constructor call uses other resources, like files, a network connection, or something similar, then those resources must be cleaned up. A constructor's catch block is the only place to do this.
    Memory is not that different from any other resource. Anything which safely manages a resource could be called a "container." What I'm saying is that exception safety should be handled at the lowest possible level. If your file manager is at this level, then obviously your file manager is going to have to handle exceptions.

    The point is that by building smart, exception-safe "bottom tier" objects as you say, you can easily propagate exception safety upward in the design.

    But what if the class doesn't use auto_ptr? What if it uses something else. It should not matter to the outside what kind of smart pointer is used internally.
    If the class doesn't use auto_ptr, then the class does not conform to the requirements of the code it is trying to call. You have to draw a line somewhere. Again, none of this REQUIRES that a client class maintain this pointer in an auto_ptr. The condition is simply that once it is passed to the constructor, it is owned by that constructed object. If the caller had a raw pointer, then the caller just has to "forget" the reference. If you're not used to using smart pointers, you are already skilled at doing that.

    Therefore a raw pointer is best. But raw pointers require extra care with exception safety. So we use extra care by using catch and rethrow.
    I hate trying to imagine all the possible paths through code during an exception, and figuring out what resources might leak or not. In my opinion exceptions should not be used to ensure proper resource release. Instead, all objects should be constructed out of other, completely exception-safe objects.

  10. #25
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by brewbuck View Post
    Memory is not that different from any other resource. Anything which safely manages a resource could be called a "container." What I'm saying is that exception safety should be handled at the lowest possible level. If your file manager is at this level, then obviously your file manager is going to have to handle exceptions.

    The point is that by building smart, exception-safe "bottom tier" objects as you say, you can easily propagate exception safety upward in the design.
    My point is that "any object constructor that does anything other than assign values to members" is a big enough exception that your simple rule doesn't seem to be useful. On everything else I agree.

    If the class doesn't use auto_ptr, then the class does not conform to the requirements of the code it is trying to call. You have to draw a line somewhere. Again, none of this REQUIRES that a client class maintain this pointer in an auto_ptr. The condition is simply that once it is passed to the constructor, it is owned by that constructed object. If the caller had a raw pointer, then the caller just has to "forget" the reference. If you're not used to using smart pointers, you are already skilled at doing that.

    I hate trying to imagine all the possible paths through code during an exception, and figuring out what resources might leak or not. In my opinion exceptions should not be used to ensure proper resource release. Instead, all objects should be constructed out of other, completely exception-safe objects.
    Yes, you can use auto_ptr as a transfer object for your pointer. It does have the advantage of providing that exception safety. But it is still more optimal to use raw pointers. It's a trade off. Sometimes one option is better, sometimes another. When writing an API, using a raw pointer is easier for the client, but harder for the API writer.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  11. #26
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    You can write a smart pointer without a single try...catch. As long as every resource handling class deals with exactly one resource, you can write completely exception-safe code without a single try...catch. If any class allocates more than one resource and wants to manage them all, it will have to use try...catch. brewbuck's rule is correct and universal.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Virtual base class
    By George2 in forum C++ Programming
    Replies: 7
    Last Post: 03-14-2008, 07:45 AM
  2. Smart pointer class
    By Elysia in forum C++ Programming
    Replies: 63
    Last Post: 11-03-2007, 07:05 AM
  3. Message class ** Need help befor 12am tonight**
    By TransformedBG in forum C++ Programming
    Replies: 1
    Last Post: 11-29-2006, 11:03 PM
  4. Member function pointer within the class
    By skorman00 in forum C++ Programming
    Replies: 1
    Last Post: 07-05-2004, 06:03 AM
  5. Virtual Base Class & Constructor :: C++
    By kuphryn in forum C++ Programming
    Replies: 2
    Last Post: 09-13-2002, 03:14 PM