我被告知可以使用泛型编程(用C ++编写)代替多态,但我从未理解如何/为什么。我总是使用泛型编程来处理我的类可以使用多种类型的情况,并且当我想要派生类的不同行为时(即标准的多态行为),我使用了polymorpshim。我只是不知道这两个(看似)不同概念之间的联系。我想你可以使用多态函数根据用户输入的数据类型展示不同的行为,但我甚至不确定这是否可行。
如何使用泛型编程而不是多态?这样做有什么好处?如果可能,请提供一个示例。
答案 0 :(得分:1)
派生类 多种类型。每个派生类都是一个类型,因此具有不同的派生类意味着有多种类型。
泛型通常优于运行时多态性,因为类型信息不会丢失 - 编译器仍然具有访问权限,因此它可以启用更大程度的类型检查。运行时多态性如何在这种情况下失败的一个简单示例是非泛型集合类型。
答案 1 :(得分:0)
在C ++中,有两种类型的多态:编译时和运行时。
编译时间多态
编译时多态性是通过使用模板完成的。依赖这种形式的多态性也称为泛型编程。
标准库中的许多函数,例如std::sort
,std::find
,都依赖于编译时多态性。只要用于实例化函数的参数支持所需的功能,那些函数就可以正常工作。
简单示例:
template <typename T>
T const& min(T const& lhs, T const& rhs)
{
return (lhs < rhs) ? lhs : rhs;
}
min
的实现将能够返回两个值的 min ,无论其类型如何,只要该类型支持操作lhs < rhs
。
运行时多态性
运行时多态性是通过使用虚函数完成的。这是更广为人知的多态性形式。
依赖于运行时多态性的函数使用基类指针或引用。它们调用在基类级别声明的虚函数。根据与对象关联的运行时信息将调用分派到派生类。
简单示例:
struct Shape
{
virtual double getArea() const = 0;
}
void foo(Shape const& s)
{
double area = s.getArea();
// Use area
}
无论具体类型如何, foo
都值得任何有效的Shape
对象。
答案 2 :(得分:0)
你需要明确你想要达到的目标;怎么应该是你的第二个问题。您可以使用多态来避免编写新代码,也可以使用它来避免更改旧代码。
如果你想要的只是一个类或一个函数来为不同的类型表现不同,那么静态多态就可以了。有时普通函数超载就足够了;有时你必须使用模板;偶尔你必须专门为边缘情况设计模板。这主要解决了编写新的冗余代码的问题:如果编译器可以为您编写它们,为什么要编写IntVectors和StringVectors。
只有在想通过基类指针引用类时才应该派生类。动态多态允许您重用现有代码而无需修改它:如果您有一个在屏幕上显示小部件的函数,则在引入新类型的小部件时不需要重写它。
现在,如果你可以结合静态和动态多态,你就有了力量。想到一个随机的例子是电子表格,但它可能不是最好的:
class BaseCell {
// ...
public:
virtual void draw() = 0;
};
template<class CellFormat>
class Cell : public BaseCell {
public:
virtual void draw(); // uses something supplied by CellFormat
};
// somewhere else
vector<shared_ptr<BaseCell>> cells {
shared_ptr<BaseCell>{new Cell<IntFormat>()},
shared_ptr<BaseCell>{new Cell<CurrencyFormat>()}
};
for (auto cell: cells) {
cell->draw();
}
通过这种方式,您可以编写使用BaseCell提供的接口的未来证明函数,减少对现有代码库的更改,并为新支持的格式生成不同的类,从而减少必须编写的新代码。
总结:运行时和静态多态不是替代,但它们是对不同行为的统一接口概念的补充技术。