3

这段代码是 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当然必须实现该方法。如今,也可以使用诸如协议之类的机制来强制实现兼容(然后声明memberid<Matter>),但根本不需要它就可以工作。

在 C++ 中,用所谓的虚函数创建一个超类是唯一的选择吗?

编辑

澄清一下,上面的代码可以看作是一个容器类方法,它返回其组件的总重量。您事先不知道容器上会出现什么,它可以是任何对象。你只知道这些对象响应消息weight


[1]面向对象编程,一种进化方法,第 2 版,1991 - Brad J. Cox,Andrew J. Novobilski - 第 4 章,第 65 页

4

2 回答 2

1

与 C++ 最接近的是具有虚函数的超类。如果您真的关心后期绑定,则使用虚拟功能,尽管在您的示例中不清楚这是否有必要。权重可能只是超类中可公开访问的数据成员。

C++ 中动态绑定的形式严格地在类层次结构上下。这允许编译器进行一定程度的检查,而不是将其全部留给运行时系统。除非你使用不安全的演员表。

请注意,您确实在 C++ 中获得了多重继承,因此您希望能够使用的类只需要从这个超类继承,但也可以从其他完全不相关的东西继承。

于 2012-03-29T14:47:18.150 回答
1

您的成员变量需要是指向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 移动语义可以使这更有效。

于 2012-03-29T14:55:54.137 回答