Пример динамического связывания в C ++ - PullRequest
3 голосов
/ 29 марта 2012

Этот фрагмент кода является классическим примером динамического связывания в 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

Итак, как программист с некоторым опытом в этом языке и делающий мой первый шаги в C ++, я хотел бы знать: как это будет реализовано в C ++, учитывая что он также поддерживает какую-то позднюю привязку?

В этом примере мы предполагаем, что каждый член может быть любого класса, однако Конечно, реализация метода weight обязательна. В наши дни механизмы аналогичные протоколы также могут быть использованы для обеспечения реализации совместим (тогда объявляется member как id<Matter>), но это не нужно в все, чтобы иметь возможность работать.

В C ++ создание суперкласса с так называемыми виртуальными функциями единственная альтернатива?

Редактировать

Просто чтобы уточнить, приведенный выше код можно рассматривать как метод класса контейнера который возвращает общий вес его компонентов. Вы не знаете заранее Что будет на контейнере, это может быть любой объект. Вы знаете только это эти объекты отвечают на сообщение weight.


[1] Объектно-ориентированное программирование, эволюционный подход, 2nd Издание, 1991 - Брэд Дж. Кокс, Эндрю Дж. Новобильски - Глава 4 Page 65

Ответы [ 2 ]

1 голос
/ 29 марта 2012

Ваша переменная-член должна быть указателем на базовый класс weighable.Такой указатель может ссылаться на любой производный экземпляр.

Поскольку указатели создают риск утечки памяти, разумно сделать его умным указателем.C ++ 11 имеет unique_ptr.Таким образом, ваш класс может выглядеть как

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;
  }
  ...
};

Чтобы инициализировать элементы с произвольными производными экземплярами weighable, вам необходимо выделить эти объекты в куче.Это может быть немного сложно, поскольку нет общего способа скопировать объекты, на которые ссылается указатель базового класса.Один из способов - сделать функцию вставки шаблоном:

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

Это можно сделать несколько эффективнее с помощью семантики перемещения C ++ 11.

1 голос
/ 29 марта 2012

Самое близкое, что вы действительно получаете с C ++, - это суперкласс с виртуальными функциями. Виртуальные функции, если вы действительно заботитесь о позднем связывании, хотя в вашем примере неясно, нужно ли это. Вес может быть просто общедоступным членом данных в суперклассе.

Форма динамического связывания в C ++ строго вверх и вниз по иерархии классов. Это позволяет компилятору выполнять определенный уровень проверки, а не оставлять все это системе времени выполнения. Если вы не используете небезопасные броски.

Обратите внимание, что вы получаете множественное наследование в C ++, поэтому классы, которые вы хотите использовать, должны наследовать только от этого суперкласса, но также могут наследовать от чего-то другого, совершенно не связанного.

...