虽然它们的核心动态绑定和模板是根本不同的东西,但它们可用于实现相同的功能。
namespace DB {
// interface
class CustomCode {
public:
virtual void operator()(char) const = 0;
};
class Lib {
public:
void feature(CustomCode const& c) {
c('d');
}
};
// user code
class MyCode1 : public CustomCode {
public:
void operator()(char i) const {
std::cout << "1: " << i << std::endl;
}
};
class MyCode2 : public CustomCode {
public:
void operator()(char i) const {
std::cout << "2: " << i << std::endl;
}
};
void use() {
Lib lib;
lib.feature(MyCode1());
lib.feature(MyCode2());
}
}
namespace GP {
//interface
template <typename CustomCode> class Lib {
public:
void feature(CustomCode const& c) {
c('g');
}
};
// user code
class MyCode1 {
public:
void operator()(char i) const {
std::cout << "1: " << i << std::endl;
}
};
class MyCode2 {
public:
void operator()(char i) const {
std::cout << "2: " << i << std::endl;
}
};
void use() {
Lib<MyCode1> lib;
lib.feature(MyCode1());
//lib.feature(MyCode2()); <-- illegal
}
}
虽然这些范例不相同并且有其优点和缺点(A
更强大(参见MyCode2
)而B
对用户更灵活)但他们都允许实现相同的功能(虽然上面提到的限制适用)。
无论如何,理论上(TM)A
在运行时由于虚函数的间接性而稍慢,而B
提供了一些很好的优化机会作为方法可以内联(当然你没有间接)
但是,我经常觉得A
更加自我记录,因为你必须实现一个清晰的界面(通常由多个方法组成),而B
则更无政府主义(这意味着它的灵活性。)
A
作为模块间接口,到目前为止我还没有真正做过大项目?)注意:说“动态绑定更好,因为它更强大”根本不是一个答案,因为前提条件是你有两种方法适用的情况(否则没有自由选择 - 至少不合理)。
答案 0 :(得分:6)
答案 1 :(得分:1)
哪个更好?这取决于。你专注于重叠。更好的方法是关注方法的分歧。你也错过了同时使用这两种方法的地方。
模板的最大优势在于它们能够有效减少千篇一律的代码。模板的另一个优点是元编程。由于SFINAE,你可以做一些真正奇怪的事情。
模板的一个缺点是语法有点笨拙。没有办法解决这个问题。就是这样。模板的另一个缺点是每个实例化都是一个不同的类,与从同一模板类实例化的其他类完全无关。有一种解决方法:结合两种方法。使您的模板类派生自一些非模板基类。当然,现在你已经失去了一些运行时间优势。
多态性的最大优点是它是动态的。这可能是巨大的,巨大的胜利。不要打折它。这种多态性存在性能损失,但是如果你想拥有一个服从公共接口的对象集合但是不同的对象具有不同的接口实现,那么你将以这种或那种方式支付这种惩罚。