C++ 什么时候应该使用模板而不是继承,反之亦然?
在许多情况下,这个问题甚至不会问自己,因为有时候继承提供了模板无法提供的必要特性。例如,当我需要通过一个基类型(多态性)处理不同的类型时,我需要使用继承 但是,在某些情况下,这个问题可以通过继承和模板来解决 以策略模式为例,如代码某些部分的参数化: 文件解析器的一种解决方案如下所示:C++ 什么时候应该使用模板而不是继承,反之亦然?,c++,templates,inheritance,C++,Templates,Inheritance,在许多情况下,这个问题甚至不会问自己,因为有时候继承提供了模板无法提供的必要特性。例如,当我需要通过一个基类型(多态性)处理不同的类型时,我需要使用继承 但是,在某些情况下,这个问题可以通过继承和模板来解决 以策略模式为例,如代码某些部分的参数化: 文件解析器的一种解决方案如下所示: class FileParser { //... public: void Parse(ParsingAlgorithm* p); //... } void FileParser::
class FileParser
{
//...
public:
void Parse(ParsingAlgorithm* p);
//...
}
void FileParser::Parse(ParsingAlgorithm* p)
{
m_whatevertypeofvaluesineed = p->Parse(whateverparametersyouneed);
}
其中ParsingAlgorithm是一个抽象基类,它提供了一些基本方法,需要由喜欢为FileParser类实现特定解析器的人继承
但是,使用模板也可以轻松实现这一点:
template <class Parser>
class FileParser
{
//...
public:
void Parse()
{
m_whatevertypeofvaluesineed = m_parser.Parse(whateverparametersyouneed);
}
private:
Parser m_parser;
//...
}
模板
类文件解析器
{
//...
公众:
void Parse()
{
m_whatevertypeofvaluesineed=m_parser.Parse(whateverparametersyouneed);
}
私人:
解析器m_解析器;
//...
}
是否有一些通用规则可以用来决定是使用模板还是使用继承?或者我应该尽可能地使用模板,以避免虚拟函数之类的运行时开销?模板提供编译时多态性,而不是继承提供的运行时多态性。如果可以,我更喜欢使用模板
这篇文章对它进行了详细的解释。我的建议是在这种情况下都不使用,而是对每种文件类型使用单独的函数
Stream stream = open(filepath);
Image image = ParseBMP(stream);
// ...or
Image image = ParseJPG(stream);
不需要让事情变得更复杂。如果您在编译时知道要操作哪些对象,那么带模板的静态多态性通常是最快的方法,它生成的代码更简洁(不需要显式继承)。它也可以更通用,因为您不受强类层次结构的限制 如果您想要运行时多态性,那么您别无选择,只能使用指针、继承和虚拟函数的轻微开销 我个人的看法是:
- 尽可能使用模板,这很舒服
- 使用继承对代码进行因式分解(但不要使用异构集合),但要小心切片
- 不要担心虚拟呼叫的性能问题
- 有时,您别无选择,希望异构集合在使用指针的痛苦中徘徊
对于您的示例,它们在功能上并不完全相同:第一个变体允许并要求您在运行时创建解析器实例,而第二个变体要求程序员在编写代码时选择解析器。您是对的,但是我的例子应该是一个快速的例子,说明在这种情况下“继承与模板”的问题可能会出现。我不同意。使用不同的函数是反对开闭原则的,以前从未听说过这个原则,但对我来说这似乎有点邪恶