【问题标题】:C++ template duck-typing vs pure virtual base class inheritanceC ++模板鸭子类型与纯虚拟基类继承
【发布时间】:2011-03-20 05:02:26
【问题描述】:

在模板鸭子类型和纯虚拟基类继承之间进行选择的准则是什么?例子:

// templates
class duck {
    void sing() { std::cout << "quack\n"; }
};

template<typename bird>
void somefunc(const bird& b) {
    b.sing();
}

// pure virtual base class
class bird {
    virtual void sing() = 0;
};

class duck : public bird {
    void sing() { std::cout << "quack\n"; }
}

void somefunc(const bird& b) {
    b.sing();
}

【问题讨论】:

  • 很好的双关语 :)(更多字符)

标签: c++ inheritance templates base-class pure-virtual


【解决方案1】:

使用模板鸭子类型,您正在执行静态多态性。因此,你不能做像

这样的事情
std::vector<bird*> birds;
birds.push_back(new duck());

但是,由于您依赖于编译时类型,因此效率更高一些(没有虚拟调用意味着没有动态调度(基于动态类型))。

【讨论】:

  • @Scharron。虚拟调用不会导致“动态类型检查”或任何类似的事情。 C++ 从不在运行时执行类型检查。
  • @Georg 我真的不明白你的意见。即使有指针,代码也不起作用,切片是无关的。
  • @John :对不起,我简化了。我的意思是动态调度。已编辑。谢谢:-)
  • @scharron: 见object slicing - 你创建了一个临时的duck,但是当它被复制到向量中时会被切片bird。您也只能获得指针或引用类型的多态行为。
  • @Georg 好的,所以你在谈论 Sharron 的代码......他说你不能做那样的事情。
【解决方案2】:

如果让事物广泛传播的“模板性质”对您来说是可以接受的,那么模板(“编译时鸭子类型”)可以为您提供惊人的速度(避免隐含在虚函数调用中的“间接级别” ) 虽然可能会在内存占用方面付出一定的代价(理论上,良好的 C++ 实现可以避免与模板相关的内存开销,但我不太相信这种高质量的编译器一定会可用在您需要移植的所有平台上;-)。因此,至少从务实的角度来看,这是一种速度/内存的权衡。如果您正在执行的操作像 I/O 一样超级慢,那么避免虚拟调用所获得的相对微小的速度增益可能对您的用例并不重要。

【讨论】:

    【解决方案3】:

    编译时间与运行时间。如果要编译时绑定,则需要使用模板。如果您在编译时不知道类型,则应使用虚拟继承。

    【讨论】:

    • 不错的简短回答。它说明了中级程序员在决定选择哪种方式时需要知道的一切(一旦他知道什么时候需要他的类型是动态的,例如将它们存储在抽象类型的容器中)。我想知道为什么这近 3 年都没有得到支持。现在它做到了:)
    【解决方案4】:

    它们是两个完全不同的东西。一个不能替代另一个。模板函数提供了一个通用操作somefunc(),它适用于一整类类型,而不仅仅是鸟类。其参数的类型必须在编译时知道。虚拟方法提供特定于鸟类的运行时多态操作。参数的确切类型 (this) 在编译时不需要知道。

    由于它们提供不同的功能,并且彼此不冲突,因此您很少需要在两种方法之间做出决定。确定您需要什么功能,明智的方法将是显而易见的。它甚至可能是两者的结合。

    (顺便说一句,这里误用了“duck typing”一词。这两种方法都不是duck typing。你应该从你的C++词典中删除这个短语。)

    【讨论】:

    • 我在很多方面都非常不同意您的回答。模板可以在 C++ 中以多种方式使用,其中一种是有效的鸭式打字,您应该更好地了解它。其次,我也不同意Decide what functionality you need, and the sensible approach will be obvious 的部分。编程并不总是直截了当,设计选择并不总是显而易见的。
    【解决方案5】:

    @John 是对的。如果你有两个协变类型参数你别无选择,你必须使用模板。面向对象技术提供运行时分派,但它仅适用于其方法最多具有一个变体参数(对象)的类型。

    最有趣的问题涉及 N 元与 N>1 的关系,因此您通常别无选择,只能使用模板。请检查标准库以了解使用最多的技术。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-11
      • 2014-05-22
      相关资源
      最近更新 更多