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?
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
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.