C++模板鸭子类型与纯虚拟基类继承

发布于 2024-09-11 07:35:02 字数 430 浏览 6 评论 0原文

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

// 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();
}

Which are the guidelines for choosing between template duck-typing and pure virtual base class inheritance? Examples:

// 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();
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

偏闹i 2024-09-18 07:35:02

使用模板鸭类型,您正在执行静态多态性。因此,您不能执行类似的操作

std::vector<bird*> birds;
birds.push_back(new duck());

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

With template duck-typing, you are doing static polymorphism. Thus, you cannot do things like

std::vector<bird*> birds;
birds.push_back(new duck());

However, since you are relying on compile time typing, you are a little more efficient (no virtual call implies no dynamic dispatch (base on the dynamic type)).

木格 2024-09-18 07:35:02

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

If having the "template nature" of things propagate widely is OK with you, templates ("compile-time duck typing") can give you blazing speed (avoiding the "level of indirection" that's implicit in a virtual-function call) though maybe at some cost in memory footprint (in theory, good C++ implementations could avoid that memory overhead related to templates, but I don't feel very confident that such high-quality compilers will necessarily be available on all platforms where you need to port;-). So, at least pragmatically, it's something of a speed/memory trade-off. If the operations you're doing are so super-slow as I/O, then maybe the relatively tiny speed gain from avoiding a virtual call isn't really material to your use case.

旧瑾黎汐 2024-09-18 07:35:02

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

Compile time vs. Runtime. If you want compile time binding you need to use templates. If you don't know the types at compile time, you should use virtual inheritence.

梦幻之岛 2024-09-18 07:35:02

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

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

(顺便说一句,术语“鸭子类型”在这里被误用了。这两种方法都不是鸭子类型。您应该从 C++ 词典中删除该短语。)

They are two completely different things. One is not an alternative to the other. The template function provides a general operation somefunc() which applies to a whole class of types, not just birds. The type of its parameter must be known at compile-time. The virtual method provides a runtime polymorphic operation specific to birds. The exact type of the parameter (this) need not be known at compile-time.

Since they provide different functionality, and are not in conflict with each other, it's rare that you ever need to decide between the two approaches. Decide what functionality you need, and the sensible approach will be obvious. It may even be a combination of the two.

(btw, the term "duck typing" is misused here. Neither approach is duck typing. You should drop the phrase from your C++ lexicon. )

不必在意 2024-09-18 07:35:02

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

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

@John is right. If you have two covariant type parameters you have no choice, you have to use templates. Object oriented techniques provide run-time dispatch but it is only available for types whose methods have at most one variant argument (the object).

Most interesting problems involve relations which are N-ary with N>1 therefore you will usually have no choice but to use templates. Please examine the standard library to see which technique is used most.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文