Nap*_*tor 12 c++ polymorphism templates
大家好我对模板和多态性有疑问.根据定义,多态性提供代码可重用性,并且模板在某种意义上允许用户通过提供具有不同数据类型的通用编程来使用相同的代码.那么使用多态而不是模板有什么好处呢.这可能是一个愚蠢的问题,但我很想知道确切的区别.
Nic*_*las 17
你似乎误解了多态性是什么.
多态性的核心与派生类无关.多态性只是意味着能够在不了解它的情况下使用类型.多态性不是使用具体类型,而是依赖于某种形式的原型来定义它所采用的类型.接受适合该原型的任何类型.
C++中的运行时多态性是通过从包含虚函数的基类派生类来提供的.基类和虚函数构成了多态原型.为接受调用这些虚函数的基类而编写的代码将接受从基类派生的任何类实例.
编译时多态性是在编译时发生的多态性;)这意味着编译器必须知道发生了什么.您可能已经针对多态原型编写了C++代码,但编译器并不关心.您可以在编译后获得具体的具体类型.
编译时多态性由C++中的模板提供.模板函数或类可以采用符合原型的任何类型,通常称为"概念".与基类和虚函数不同,原型是隐式的:原型仅由模板函数/类使用类型定义.
如果你有这个模板功能:
template<typename T>
void Stuff(T &t)
{
t.call(15);
}
Run Code Online (Sandbox Code Playgroud)
有一个隐含的要求T.这个要求是它有一个名为的成员函数call.此成员函数必须有一个重载,可以使用整数值调用.
这意味着可以使用恰好适合此原型的任何类型.
模板多态性比继承多态更广泛,因为它可以被更广泛的类型使用.必须专门设计一种类型才能使用继承多态性; 你必须从一个阶级派生出来.类型可以是非破坏性的(即:您不必更改类型本身)适应模板多态性.如果你的模板原型设计得很好,那就更好了:
template<typename T>
void Stuff(T &t)
{
call(t, 15);
}
Run Code Online (Sandbox Code Playgroud)
所有这个版本Stuff需要的是有一些函数需要一个T&整数值.如果我有一些我想要使用的类型,我Stuff所要做的就是call在适当的命名空间中定义一个函数(即,在其中定义类型的命名空间).这将很好地工作.所有这些都没有修改类型本身.
当然,编译时多态是......编译时.如果我想要一些用户输入或数据文件来选择多态类型,模板将不会帮助很多(虽然类型擦除,基于模板的技术,可以帮助).运行时多态性的主要好处是它确实是运行时.
另一个好处是它的原型更精确.关于继承的一切都是明确的.基类中的虚函数接口清晰可见.编译器将阻止您尝试错误地使用该基类(调用其上不存在的方法).实际上,一个体面的IDE将指导您的代码,以便您只能看到基类上的方法.
模板多态性更隐含.由于C++无法拼写出特定模板函数/类放在某个类型上的原型,因此很容易意外地在模板类型上调用某些不应该的东西.当您尝试使用不适合原型的类型时,编译器将仅检测到此情况.即使这样,你通常会得到一个巨大的错误喷射(取决于你的模板代码的嵌套程度),这使得很难知道问题出在哪里.
实现隐式模板多态原型也要困难得多,因为它没有拼写出来.实现派生类需要遍历基类,查看所有虚函数并实现它们.为模板原型执行此操作要困难得多,除非有某些文档可以解释它.如果你没有实现某些东西,你会再次得到一个错误的喷射,这个错误通常比即将发生的问题还少.