Search code examples
c++objective-clate-bindingdynamic-binding

Dynamic Binding Example in C++


This piece of code is a classical example of dynamic binding in Objective-C [1]:

float total = tareWeight;     // start with weight of empty container
int i, n = [self size];       // n = number of members
for (i = 0; i < n; ++i) {     // loop over each member
    id member = [self at:i];  // get next member
    total += [member weight]; // accumulate weight of contents
}
return total;                 // return total weight to caller

So, as a programmer with some experience in this language and doing my first steps in C++, I'd like to know: how would this be implemented in C++, given that it also supports some kind of late binding?

In this example, we assume that each member can be of any class, however implementing the weight method is a must, of course. These days mechanisms like protocols could be used as well, to enforce the implementation to be compatible (then declaring member as id<Matter>) but it's not needed at all to be able to work.

In C++, Would creating a super class with the so called virtual functions be the only alternative?

Edit

Just to clarify, the above code can be seen as a container class method which returns the total weight of its components. You don't know in advance what will be on the container, it can be any object. You only know that these objects respond to the message weight.


[1] Object-Oriented Programming, an Evolutionary Approach, 2nd Edition, 1991 - Brad J. Cox, Andrew J. Novobilski - Chapter 4 Page 65


Solution

  • You member variable would need to be a pointer to the weighable base class. Such a pointer can refer to any derived instance.

    Since pointers bring about memory leak risk, it's clever to make it a smart pointer. C++11 has unique_ptr. So you class could look like

    class heavyContainer {
      std::vector<std::unique_ptr<weighable>> members;
     public:
      float total_weight() {
        float result = tareWeight;
        for(auto& member: members)
          result += member->weight();
        return result;
      }
      ...
    };
    

    To initialize members with arbitrary derived instances of weighable, you need to heap-allocate these objects. That can be a bit tricky since there is no general way to copy objects referred to by a base class pointer. One way is to make the insertion function a template:

    template<class WeighableDerivedObject>
    heavyContainer::insert(const WeighableDerivedObject& obj){
      members.push_back(new WeighableDerivedObject(obj));
    }
    

    This could be made a bit more efficient with C++11 move semantics.