Question

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

Was it helpful?

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.

OTHER TIPS

The closest you really get with C++ is a super class with virtual functions. Virtual functions if you really care about late binding, although in your example it isn't clear whether that is necessary. Weight could just be a publicly accessible data member in the super class.

The form of dynamic binding in C++ is strictly up and down the class hierarchy. This allows the compiler to do a certain level of checking rather than leaving it all to the run-time system. Unless you use unsafe casts.

Note that you do get multiple inheritance in C++, so the classes you want to be able to use only have to inherit from this superclass but can also inherit from anything else totally unrelated.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top