Thread: I'm misunderstanding dynamic binding

  1. #1
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446

    I'm misunderstanding dynamic binding

    I'm not being able to properly access dynamic binding from inside one of my derived classes member function definition.

    CContainer is a derived of CItem. The former adds a ContentsWeight() member.

    CContainer also adds a add() member. And this is where I'm having troubles:
    Code:
    CContainer& CContainer::add(CItem* obj) {
    
    /* ... */
    int objW = obj->weight() + obj->ContentsWeight();
    /* ... */
    }
    I can understand why I can't do this and why I get an error saying that ContentsWeight is not a member of CItem. After all, obj could be some other type of derived object, or the base itself. Only CContainer declares ContentsWeight.

    But I'm not sure how to best solve this. I do need to access ContentsWeight on that code.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  2. #2
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    If you need to access ContentsWeight, then the function parameter should be a CContainer* instead of a CItem*. Perhaps you have an issue where you have a vector or set of CItem*'s that include CContainer*'s (or smart pointer versions) and at this point you know that this is a CContainer, but you just have the CItem*. At this point you can use a static_cast to convert it (again, this assumes you know it is a CContainer*), and then spend some time making sure your class design is correct.

    If CContainer's require some special handling that other CItem's don't require, perhaps they shouldn't be held together as CItem*'s. Or perhaps whatever special case you need for CContainer can be implemented as a generic method for CItem with a special override for CContainer.

    Just looking at the code in question, I would say that the weight of a container should include the weight of it and its contents, so there should be no need for a ContentsWeight(), but instead weight() should be overridden by CContainer to return the weight of the contents. If you need both, then perhaps CItem should have both an ItemWeight() and a TotalWeight() method.

  3. #3
    Registered User
    Join Date
    Nov 2001
    Posts
    1,348
    dynamic_cast()

    Kuphryn

  4. #4
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Ah, yes. dynamic_cast.

    Although I tend to believe if I need it, something is probably wrong with my hierarchy.

    Quote Originally Posted by Daved
    Just looking at the code in question, I would say that the weight of a container should include the weight of it and its contents, so there should be no need for a ContentsWeight(), but instead weight() should be overridden by CContainer to return the weight of the contents. If you need both, then perhaps CItem should have both an ItemWeight() and a TotalWeight() method.
    I do need both since I make a distinction between the weight of an empty container (which is the weight of the container itself) and the overal weight of the container (the sum of its weight plus its contents).

    All other deriveds of CItem (CWeapon and CArmor) don't need this.
    Also, every other member but this one, is a very strong case for a CContainer Is-A CItem relationship. So it would be hard for me to remove it of CItem.

    Maybe... if I overload it?

    CContainer& CContainer::add(CItem* obj)
    CContainer& CContainer::add(CContainer* obj)
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  5. #5
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    If you're never going to use add() on other items, just use CContainer& CContainer::add(CContainer* obj)
    You will get errors if you pass in something different, as you know.

  6. #6
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Oh...

    add() will add any item to the container. A sword, an armor, a potion or another container. It's only when it adds another container that I need to check its weight differently.

    I have a chest and I add a bag inside it. The weight of the bag is calculated by summing the weight property of the bag itself plus the weight of the bag contents. If I add a sword to the chest I just need the sword weight. And the same with an armor or potion.
    Last edited by Mario F.; 07-24-2006 at 12:54 PM.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  7. #7
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Apparently, you have two distinct properties of an item. One is the weight of an item. The other is the weight of the item and anything it holds. Make two functions in CItem. The first is the ItemWeight. Implement that as you have your weight() function. The second is ItemAndContentsWeight. Implement that with a call to ItemWeight() for anything that cannot contain other objects. Override it in classes that can contain other objects to return the item weight and the weights of what is contained.

    When you need the item weight without the weight of what is contained, use ItemWeight(). When you need the item weight plus anything it contains, as you do in this case, use ItemAndContentsWeight(). There is no need to know whether it is a CContainer or not, there is no need to use a dynamic_cast or any other RTTI. Plus, if in the future you add some other item that can hold something (perhaps a belt that holds a sword, knife and keys) you already have the setup to implement it generically.

  8. #8
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Ah. Thanks Daved.

    I was resisting doing just that. But you did give me a good reason to do so.

    ... was already casting the pointer
    Last edited by Mario F.; 07-24-2006 at 01:21 PM.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  9. #9
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Quote Originally Posted by Mario F.
    Maybe... if I overload it?

    CContainer& CContainer::add(CItem* obj)
    CContainer& CContainer::add(CContainer* obj)
    The problem is that overloads are resolved at compile time using the static type of the argument. I.e. if you have a CItem * that points to a CContainer, it would still call the CItem* overload.
    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

  10. #10
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    hmm... not if add is virtual. Correct?
    In that case it will resolve to the dynamic type
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  11. #11
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    No, it will still resolve to the static type. Only the object the function is called on is considered at runtime, all parameters are strictly compile-time.
    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

  12. #12
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Ah! thanks.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. boost::shared_ptr and dynamic binding
    By Mario F. in forum C++ Programming
    Replies: 2
    Last Post: 07-24-2006, 03:50 PM
  2. Dynamic binding
    By Mario F. in forum C++ Programming
    Replies: 5
    Last Post: 07-09-2006, 04:37 PM
  3. dynamic binding
    By freethenet in forum Networking/Device Communication
    Replies: 2
    Last Post: 10-26-2004, 03:31 PM
  4. dynamic or static binding
    By noob2c in forum C++ Programming
    Replies: 1
    Last Post: 08-06-2003, 01:43 PM
  5. Static Binding & Dynamic Binding :: C++
    By kuphryn in forum C++ Programming
    Replies: 2
    Last Post: 12-31-2001, 08:51 PM